【问题标题】:How to resolve promises one after another?如何解决一个又一个的promise?
【发布时间】:2016-01-20 00:21:16
【问题描述】:

我怎么能一个接一个地兑现承诺?

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

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 秒记录一次语句,这意味着所有的 Promise 都是一次调用的。

我设法通过这样的回调解决了这个问题,但这让一切变得非常丑陋:

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/

【问题讨论】:

标签: javascript node.js callback promise


【解决方案1】:

您可以将 Promise 放入数组并使用 reduce 链接它们,从一个额外的已解决 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);

【讨论】:

    【解决方案2】:

    我找到了你的解决方案。

    您需要让每个then 返回一个新的承诺,以便下一个then 在前一个得到解决后做出反应。

    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/

    【讨论】:

    • 很高兴能帮上忙,马克斯!
    • 请修正参数resolve, reject。传递给.then() 处理程序的是一个不应命名为resolvereject 的单个值。
    • 根据@jfriend00 的建议修复。
    【解决方案3】:

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

    也可以创建持续时间值数组,使用Array.prototype.shift() 调用waitFor,每个持续时间值连续,或将参数timeout 传递给waitFor;如果在每个 .then() 调用相同的进程,则在 waitFor 中包含链接到 Promise.then() 的进程;在.then() 调用相同的函数waitFor 链接到初始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)})
    

    【讨论】:

    • 为什么只有一个返回值?
    • @MaxMastalerz initial waitFor 返回初始 Promise.then() 在初始调用 waitFor(1000) 后只需要返回承诺到链中的最后一个 .then()
    【解决方案4】:

    调用和等待的格式有点偏离,你的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/>');
    })
    

    【讨论】:

      猜你喜欢
      • 2018-01-24
      • 1970-01-01
      • 2023-03-31
      • 2019-08-03
      • 2020-10-06
      • 2020-09-12
      • 2016-06-29
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多