Promise resolving too early. How to make it wait till the content updates?

Hey,

I made this simple Promise:

https://jsfiddle.net/Rycerz_Andromedy/thmg4rox/2/

Myy promlem is i can’t make resolve() wait until the changed html element (in my example just text) is updated, visibly updated (the repainting of the website is finished).

I thought i will find in docs something like :

if (browserIsUpdatingSomething === false) {
resolve();
}

but i can’t find anything similar.

Any ideas? :slight_smile:

For this fine-grain level of control in your code, you’ll probably need to use a generator function. However, I would simply rethink the order of events here - have the DOM manipulation occur before asyncWork() begins.

This version doesn’t change it. The prompt still shows up before DOM updates.

$(function() {

document.getElementById('text').innerHTML += " is ok";

var asyncWork = new Promise(function(resolve, reject) {
var arr = [];
for (var i = 0; i < 9999999; i++) {
// time-consuming array pushing...
arr.push(i*0,3);
}
// i would like resolve to wait for innerHTML to repaint this:

resolve();
});
asyncWork.then(function() {
alert('alert box befor changing innerHTML');
});


}); // end ready

I will look into generator though :slight_smile: Have a good day :grin:

One thing to remember (a very important thing) is that Promises are for asynchronous code.

But Javascript code is synchronous and blocking, in general. Unless you are using things like fetch() or XHR requests, or doing things in a worker process.

Also, another important thing to remember is that the function you pass to

new Promise();

Is executed immediately before the promise even returns. This being a very long, blocking bit of code will stop all other code from executing.

So the way you have it structured means it will always execute your entire time-consuming array loop, before ever returning the promise. You will never get the result you want with that approach.

This means you have to do something to get your code to give up control for a bit so other stuff can execute. This could be, as suggested above, a generator, where you can yield to other code, or you can use something as simple as setTimeout.

setTimeout essentially says, I would like to execute function x, y milliseconds from now. Of course JS is blocking, and other code may be running, so that really means as “as soon as possible - but no earlier than y milliseconds”.

What using setTimeout does is free up the JS engine to continue processing other code. It takes the function passed to it and puts it at the end of the queue of functions that need processing and will process it as soon as possible after the specified time has passed. It has the effect of making your code asynchronous.

If you re-arranged your function to process in chunks, you could get the result you are after. (This also has the handy effect of not freezing your interface and allowing you to update the interface based on processing progress as well).

This example could be cleaned up a bit more, but I’ve put a solution for it on codepen here:

A promise based loop processor.

Hope that helps!

~Micheal

2 Likes