How can I tell when changes to jquery html() have finished?
I'm using jQuery to change the HTML of a tag, and the new HTML can be a very long string.
$("#divToChange").html(newHTML);
I then want to select elements created in 开发者_如何学Pythonthe new HTML, but if I put the code immediately following the above line it seems to create a race condition with a long string where the changes that html() is making may not necessarily be finished rendering. In that case, trying to select the new elements won't always work.
What I want to know is, is there an event fired or some other way of being notified when changes to html() have finished rendering ? I came across the jQuery watch plugin, which works alright as workaround but it's not ideal. Is there a better way ?
As a commenter already mentioned, JavaScript is single threaded, so you can't get race conditions.
What may trip you up however, is the fact that the UI will not update itself based on JavaScript, until a thread is finished. This means that the entire method must finish, including all code after you call html(...)
, before the browser will render the content.
If your code after calling html(...)
relies on the layout of the page being recalculated before continuing, you can do something like this:
$("#divToChange").html(newHTML);
setTimeout(function() {
// Insert code to be executed AFTER
// the page renders the markup
// added using html(...) here
}, 1);
Using setTimeout(...)
with a time of 1
in JavaScript defers execution until after the current JavaScript code in the calling function finishes and the browser has updated the UI. This may solve your problem, though it is difficult to tell unless you can provide a reproducible example of the error you're getting.
It's 7 years latter and I just ran into a scenario exactly like the one @mikel described, where I couldn't avoid a "timer based solution". So, I'm just sharing the solution I developed, in case anyone out there is still having issues with this.
I hate having setTimeout
s and setInterval
s in my code. So, I created a small plugin that you can put where you think it's best. I used setInterval
, but you can change it to setTimeout or another solution you have in mind. The idea is simply to create a promise and keep checking for the element. We resolve the promise once it is ready.
// jquery.ensure.js
$.ensure = function (selector) {
var promise = $.Deferred();
var interval = setInterval(function () {
if ($(selector)[0]) {
clearInterval(interval);
promise.resolve();
}
}, 1);
return promise;
};
// my-app.js
function runWhenMyElementExists () {
// run the code that depends on #my-element
}
$.ensure('#my-element')
.then(runWhenMyElementExists);
use .ready jQuery function
$("#divToChange").html(newHTML).ready(function () {
// run when page is rendered
});
精彩评论