如何化解一个又一个的承诺

How to resolve promises one after another?

本文关键字:承诺 一个又一个 何化解      更新时间:2023-09-26

我怎么能一个接一个地做出承诺呢?

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

不幸的是这个控制台。每隔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/

我找到你的解决方案了。

你需要让每个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/

你可以将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);

调用和等待的格式有点off,您的then应该是一个返回承诺的函数,因为现在您正在传递一个函数调用而不是一个函数,它立即运行该请求,而不是等待调用函数作为承诺的结果。

应该这样做:

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()似乎在.then()时立即被调用;请尝试从.then()匿名函数中返回waitFor()

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