I'm working with a proxy object
where I detect a object value change and then load new content via AJAX, I use a setInterval
function to wait until a the element that es in the AJAX request exist and then execute a piece of code. I'm doing in this way because my case requires it. I made a short snippet example:
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var clearTimeSearchProxy = setInterval(function() {
if ($("p").length) {
console.log("The element finally exist and we execute code");
clearTimeout(clearTimeSearchProxy);
}
}, 100);
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
globalHandler.makeThings = 1;
//This element es with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src=".3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
I'm working with a proxy object
where I detect a object value change and then load new content via AJAX, I use a setInterval
function to wait until a the element that es in the AJAX request exist and then execute a piece of code. I'm doing in this way because my case requires it. I made a short snippet example:
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var clearTimeSearchProxy = setInterval(function() {
if ($("p").length) {
console.log("The element finally exist and we execute code");
clearTimeout(clearTimeSearchProxy);
}
}, 100);
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
globalHandler.makeThings = 1;
//This element es with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
Now I'm wondering about how to improve the code in a cleaner, efficient and elegant way. I was thinking of using promises
instead of setInterval
to execute a code when the element that es via AJAX exists in the DOM
.
How can I make it work? Should I use other JavaScript functionality for this case instead of promises
? I'm stuck with the promise to achieve what I need, this what I have tried so far.
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var myFirstPromise = new Promise((resolve, reject) => {
if ($("p").length) {
resolve("Exist");
} else {
reject("It doesnt exist.");
}
});
myFirstPromise.then((data) => {
console.log("Done " + data);
}).catch((reason) => {
console.log("Handle rejected promise: " + reason);
});
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
globalHandler.makeThings = 1;
//This element es with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
Share
Improve this question
edited Aug 8, 2019 at 6:48
BSMP
4,8078 gold badges35 silver badges45 bronze badges
asked Aug 7, 2019 at 9:56
SilverSurferSilverSurfer
4,3666 gold badges26 silver badges55 bronze badges
1
- 1 Does this answer your question? How to wait until an element exists? – Igwe Kalu Commented Jan 18, 2020 at 18:29
3 Answers
Reset to default 5Do not wait. Rather subscribe for notification of a change in the target element.
The API to utilise for listening to changes in the DOM tree is the MutationObserver.
The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature which was part of the DOM3 Events specification.
Use it to observe change in an element as follows:
// You selected `$("p")` in your snippet, suggesting you're watching for the inclusion of 'any' `p` element.
// Therefore we'll watch the `body` element in this example
const targetNode = document.body;
// Options for the observer (which mutations to observe)
const config = {
attributes: false,
characterData: false,
childList: true,
subtree: true
};
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
for(let mutation of mutationsList) {
if ( mutation.type === "childList" ) {
continue;
}
const addedNodes = Array.from( mutation.addedNodes) ;
if ( addedNodes && addedNodes.some( node => node.nodeName === "P" ) ) {
observer.disconnect();
console.log("The element finally exist and we execute code");
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
I finally made it with MutationObserverinterface
in an easy way instead of with promises
.
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var observer = new MutationObserver(function(mutations) {
if ($("p").length) {
console.log("Exist, lets do something");
observer.disconnect();
}
});
// start observing
observer.observe(document.body, {
childList: true,
subtree: true
});
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
$("p").remove();
globalHandler.makeThings = 1;
//This element es with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
rxjs can highly simplify what you are trying to do. A very basic implementation, using only a Subject and subscription:
const {
Subject
} = rxjs;
const sub = new Subject();
sub.subscribe(e => {
console.log(`received data ${e}`);
// do your thing
});
// simulate something async
setTimeout(() => {
sub.next('foo');
}, 1000);
<script src="https://unpkg./[email protected]/bundles/rxjs.umd.min.js"></script>