0

Lets say i have 2 promises promise1, promise2 that go off and do something asynchronously.

promise2 depends on promise1 being done before running itself. This is easy enough.

function runPromises(){
    return promise1().done(function(){
       promise2();
    });
}

The problem is i also want to know when they have both finished.

runPromises().done(function(){
   alert("promise 1 and 2 done");
});

currently runPromises is alerting when promise1 is done not both.

4imble
  • 13,979
  • 15
  • 70
  • 125
  • If promise2 can only be started after promise1 is complete then can't you just wait for 2 to be complete? – Jon Mar 16 '15 at 11:33
  • Do you need to return promise2() ? – bm1729 Mar 16 '15 at 11:37
  • I tried returning promise2() and got `TypeError: Cannot read property 'done' of undefined`. I believe runPromises in that case will not be a promise until promise1 is done and so will result in it being undefined. – 4imble Mar 16 '15 at 11:39

4 Answers4

2

Here is an example using two simple functions called process1 and process2. These functions go off and do something asynchronously (in this case I'm just using setTimeout to simulate this) and return promises (using q library for this). Process 1 runs and then process 2 runs and there is room for doing something when process 2 returns. Hope this helps:

var process1 = function() {
        var deferred = q.defer();
        setTimeout(function() {
            deferred.resolve();
        }, 10);

        return deferred.promise;
    };

    var process2 = function() {
        var deferred = q.defer();
        setTimeout(function() {
            deferred.resolve();
        }, 10);

        return deferred.promise;
    };

    process1()
        .then(process2)
        .then(function() {
            // Process 1 and 2 have completed
        });
bm1729
  • 2,315
  • 3
  • 21
  • 30
  • Looks good, but I would rather not bring in a new library. I haven't looked at Q but will do now. I'm interested in seeing what it gives me above what i get in jquery. – 4imble Mar 16 '15 at 12:45
  • Would you mind using jQuery promises in your exmple? – Bergi Mar 16 '15 at 12:45
1

To chain promise actions, and get a promise for the second result (i.e. when both are done), use the then method instead of done:

function runPromises(){
    return promise1().then(function(){
//                    ^^^^
        return promise2();
//      ^^^^^^ always return promise from async functions like this callback
    });
}

You might even shorten this to return promise1().then(promise2); if you don't care about the arguments.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • This works too, seems that i missed the subtle difference between .done() and .then(). Many thanks for showing me the error of my ways :) – 4imble Mar 16 '15 at 13:07
  • 1
    @4imble - really no reason to ever use `.done()` in my opinion. It is not part of the standard and `.then()` covers the same purpose. – jfriend00 Mar 16 '15 at 21:31
0

Use then to chain promises:

 promise1().then(promise2).then(promise3).done(function(){
        alert("promise 1 and 2 and 3 done");
    });

Edited:

function runPromises(){ 
   return promise1().then(promise2).then(promise3);
}
runPromises().done(function(){console.log('all done!')});
Kris Ku
  • 1,507
  • 1
  • 16
  • 32
  • This would work in this case but i want to implement the done condition elsewhere. as in my example where i call runPromises() – 4imble Mar 16 '15 at 12:43
-3

Typical, i tried for 30 mins trying to come up with a solution for this before posting a question but now i have found the answer.

I can do this by newing up a $.Deferred();

function runPromises(){
    var d1 = new $.Deferred();
    promise1().done(function(){
       promise2().done(function(){
           d1.resolve();
       };
    });

    return d1.promise();
}

runPromises().done(function(){
   alert("promise 1 and 2 done");
});
4imble
  • 13,979
  • 15
  • 70
  • 125