如何一个接一个地解决承诺?

时间:2015-10-21 05:55:25

标签: javascript node.js callback promise

我怎么能一个接一个地发起承诺?

waitFor(t)是一个函数,它返回一个在t时间后解析的promise。我希望能够做到的是:

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

以下是我的尝试:

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

不幸的是,这个console.logs每隔1秒就记录一次,这意味着所有一次调用的承诺。

我设法用这样的回调解决了这个问题,但这让一切变得非常难看:

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

那么我应该怎么做才能使它有效,但却没有使用丑陋的回调地狱呢?

不受欢迎的结果:http://jsfiddle.net/nxjd563r/1/

期望的结果:http://jsfiddle.net/4xxps2cg/

4 个答案:

答案 0 :(得分:3)

我找到了你的解决方案。

您需要让每个then返回一个新的承诺,以便下一个then可以在前一个{1}}解决之后作出反应。

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/

答案 1 :(得分:2)

您可以将promises放入数组并使用reduce将它们链接起来,从一个额外的已解决的承诺开始。

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

答案 2 :(得分:1)

waitFor()似乎立即在.then()被调用;尝试从waitFor()匿名函数中返回.then()

可以创建持续时间值数组,使用Array.prototype.shift()连续调用waitFor每个持续时间值,或者将参数timeout传递给waitFor;如果在每个.then()调用相同的流程,请将.then()中的流程包含在Promise中的waitFor;在waitFor链接到初始.then()调用

的同一个函数waitFor()调用
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)})

答案 3 :(得分:0)

调用和等待的格式有点偏,你的then应该是一个返回一个promise的函数,因为现在你传递一个函数调用而不是一个函数,它立即运行该请求而不是由于承诺等待调用该函数。

这应该这样做:

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/>');
})