Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve promises one after another?

How could I fire off promises one after the other?

waitFor(t), is a function that returns a promise that resolves after t time. What I wish to be able to do with that is:

waitFor(1000) Then when finished, console.log('Finished wait of 1000 millis') then
waitFor(2000) Then when finished, console.log('Finished wait of 2000 millis') then
waitFor(3000) Then when finished, console.log('Finished wait of 3000 millis')

Here is what I tried:

waitFor(1000).then(function(resolve, reject) {
    console.log(resolve);
}).then(waitFor(2000).then(function(resolve, reject) {
    console.log(resolve);
})).then(waitFor(3000).then(function(resolve, reject) {
    console.log(resolve);
}));

Unfortunately this console.logs the statements each 1 second after another, which means that the promises where all called at once.

I managed to fix this with callbacks like so, yet that makes everything very ugly:

waitFor(1000).then(function(resolve, reject) {
    console.log(resolve+' @ '+(new Date().getSeconds()));
    waitFor(2000).then(function(resolve, reject) {
        console.log(resolve+' @ '+(new Date().getSeconds()));
        waitFor(3000).then(function(resolve, reject) {
            console.log(resolve+' @ '+(new Date().getSeconds()));
        });
    });
});

So how should I do this with promises that makes it work, yet isn't using ugly callback hell?

Undesired result: http://jsfiddle.net/nxjd563r/1/

Desired result: http://jsfiddle.net/4xxps2cg/

like image 980
Max Avatar asked Jan 31 '26 13:01

Max


2 Answers

I found your solution.

You need to have each then to return a new promise, so that the next then can react once the previous one has been resolved.

waitFor(1000).then(function(result) {
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
    return waitFor(2000);
}).then(function(result) {
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
    return waitFor(3000);
}).then(function(result) {
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
});

jsfiddle http://jsfiddle.net/4xxps2cg/2/

like image 128
Tiago Romero Garcia Avatar answered Feb 03 '26 01:02

Tiago Romero Garcia


You can put promises into array and use reduce to chain them, starting with one extra resolved promise.

function waitPromise(time) {
  //console.log(time);
  return new Promise( (resolve,reject) => {
    setTimeout( () => {resolve('resolved');}, time);
  });
}

function log(data) {
  return new Promise( (resolve,reject) => {
    console.log( data +' @ '+(new Date().getSeconds()));
    resolve();
  });
}

var ps = [];
for (var i=0;i<3;i++) {
  let time = (i+1) * 1000;
  ps.push( () => waitPromise(time) );
  ps.push( log );
}


console.log( 'started' +' @ '+(new Date().getSeconds()));
var p = Promise.resolve();
ps.reduce( (p,c) => {return p.then(c)}, p);
like image 35
mugiseyebrows Avatar answered Feb 03 '26 01:02

mugiseyebrows