最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to resolve promises one after another? - Stack Overflow

programmeradmin1浏览0评论

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: /

Desired result: /

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/nxjd563r/1/

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

Share Improve this question edited Oct 21, 2015 at 6:01 Max asked Oct 21, 2015 at 5:55 MaxMax 2,8462 gold badges26 silver badges35 bronze badges 3
  • This might help - tech.transferwise./making-serial-xhr-calls-in-angularjs – FrailWords Commented Oct 21, 2015 at 6:03
  • I'm not even using angularjs.... – Max Commented Oct 21, 2015 at 6:04
  • I pointed to the blog to get an idea - go for a recursive function which will go through your array of promises. – FrailWords Commented Oct 21, 2015 at 6:06
Add a ment  | 

4 Answers 4

Reset to default 3

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/4xxps2cg/2/

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);

The format for calling and waiting is a bit off, your then should be a function that returns a promise, since now you're passing a function call instead of a function, its running that request instantly instead of waiting to call the function as a result of the promise.

This should do it:

function waitFor(timeout) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(`Finished waiting ${timeout} milliseconds`);
        }, timeout);
    });
}

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

waitFor() appear to be called immediately at .then() ; try returning waitFor() from within .then() anonymous function.

Could alternatively create array of duration values , use Array.prototype.shift() to call waitFor with each duration value in succession , or pass parameter timeout to waitFor ; if same process called at each .then() , include process at .then() chained to Promise in waitFor ; call same function waitFor at .then() chained to initial waitFor() call

var t = [1000, 2000, 3000];
function waitFor(timeout) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve("`Finished waiting ${timeout} milliseconds`");
        }, timeout && t.shift() || t.shift());
    }).then(function (data) {
      $('#result').append(data + ' @ ' + new Date().getSeconds() + '<br/>'); 
    })
}

waitFor().then(waitFor).then(waitFor)
//.then(function() {return waitFor(5000)})
发布评论

评论列表(0)

  1. 暂无评论