Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$.Deferred: How to detect when every promise has been executed

I have a number of async tasks that need to be completed, so I'm using promises.

I need to detect when each one of the promises has been executed (both resolved and rejected). I must not continue execution until that point.

I was using something like this:

$.when(promise1, promise2, ...).always();

But this code is wrong, because the when method has lazy evaluation, and it returns as soon as one of the promises fails. So the always callback also runs as soon as one of the promises fail.

I was thinking in coding a workaround, but this use case is so common that maybe somebody has done it already, or maybe there's even a way of doing this using just jQuery (if not, it would be nice to add a Promise.whenNonLazy or a Promise.when(promise1, promise2, ..., false) in the future.

Is this possible?

like image 736
Mister Smith Avatar asked Oct 04 '13 08:10

Mister Smith


People also ask

How do I know if my promise is finished?

To check if a promise if is finished, you can use Promise. race - it will not wait for pending promise if given non-promise value, e.g. Note that this method gives the result asynchronously - await is necessary to check if promise is finished.

Does promise all execute all promises?

Promise.all() The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.

Are promises executed asynchronously?

A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.

How do you wait until a promise is resolved?

You can use the async/await syntax or call the . then() method on a promise to wait for it to resolve. Inside of functions marked with the async keyword, you can use await to wait for the promises to resolve before continuing to the next line of the function. Copied!


1 Answers

More sophisticated promise libraries have an allSettled() function like Q or Promise.settle like Bluebird.

In jQuery, you could implement such a function yourself as well and extend the $ namespace with it, but that will only be necessary if you need it often and performance-optimized.

A simpler solution would be to create a new promise for each of the ones you are waiting for, and fulfilling them even when the underlying one is rejected. Then you can use $.when() on them without problems. In short:

// using Underscore's .invoke() method:
$.when.apply(null, _.invoke(promises, "then", null, $.when)).done(…)

More stable:

$.when.apply($, $.map(promises, function(p) {
    return p.then(null, function() {
        return $.Deferred().resolveWith(this, arguments);
    });
})).then(…);

You might change the then callbacks a bit to distinguish between fulfilled and rejected results in the final done.

like image 181
Bergi Avatar answered Sep 22 '22 12:09

Bergi