你如何同步解决一系列es6承诺?

时间:2015-02-23 20:43:55

标签: javascript promise

我有一个返回promise的库中的函数。我需要多次运行此函数,但每次迭代必须等到上一个任务完成。

我的假设是我能做到这一点:

promiseReturner(1)
  .then(promiseReturner(2)
  .then(promiseReturner(3)
  .then(...)

使用循环可以简化:

var p = Promise.resolve();
for (var i=1; i<=10; i++) {
  p = p.then(promiseReturner(i));
}

但是,当我这样做时,链中的每个承诺都会同时执行,而不是.then()似乎意味着一个接一个地执行。很明显,我遗漏了一些关于承诺的基本信息 - 但在阅读了几篇教程和博客文章后,我仍然迷失了。

Here's a codepen I wrote up to demonstrate my attempt

6 个答案:

答案 0 :(得分:23)

您的“非循环”解决方案也不应该起作用。您必须将函数传递给.then,而不是承诺:

var p = Promise.resolve();
for (var i=1; i<=10; i++) {
  (function(i) {
      p = p.then(function() {
          return promiseReturner(i);
      });
  }(i));
}

如果该函数返回一个promise,那么你就会得到那个链接效果。

有关MDN上的承诺的更多信息。


可以使用let(和箭头功能)进行简化:

var p = Promise.resolve();
for (let i=1; i<=10; i++) {
    p = p.then(() => promiseReturner(i));
}

.bind(即ES5):

var p = Promise.resolve();
for (var i=1; i<=10; i++) {
    p = p.then(promiseReturner.bind(null, i));
}

答案 1 :(得分:2)

如果您使用的是es6,则可以使用array.reduce实现此目的。我觉得很整洁。

const functions = [/* array of functions which return promises */];
const finalPromise = functions.reduce(async (promise, asyncFn) => {
  await promise;
  return asyncFn();
}, Promise.resolve());

答案 2 :(得分:1)

您可以使用async/await使用es6生成器和co等库。

co(function* () {
  while(upto < 10) {
    var result = yield Promise.resolve(true);
  }
  return result;
}).then(function (value) {
  console.log(value);
}, function (err) {
  console.error(err.stack);
});

以下是一些详细信息:http://davidwalsh.name/async-generators

答案 3 :(得分:1)

这是我用来解决同样问题的解决方案:

var recursiveFunction = function(values) {
  return new Promise(function(resolve, reject) {
    if (values.length <= 0) {
        return resolve();
    } else {
        return promiseReturner(values[0]).then(function() {
            values.shift();
            return recursiveFunction(values).then(function() {
              resolve();
            });
        });
      }
  });
}

recursiveFunction([1,2]).then(function(r) {
 console.warn('Finished solving promises sequentially');
})

答案 4 :(得分:0)

相对于彼此同步执行Promise可能很棘手。我在下面提供了一个使用Axios Promise的示例,但是您可以将其替换为自己的Promise。祝你好运!

past_tense=[]
for i in words:
    if i[-1]=='e':
         words.append('d')
    else:
         words.append('ed')
past_tense=words

答案 5 :(得分:-1)

您可以通过nsynjs运行代码,它会暂停每个返回promise的函数的执行,并等到promise被解决:

var promiseReturner = function(i) {
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve("result is "+i)
        }, 1000);
    });
};

function synchronousCode() {
    for (var i=1; i<=10; i++) {
        var p=promiseReturner(i); // nsynjs will pause here until promise is resolved
        console.log(p.data); // `data` will contain result of the promise
    }
};
	
nsynjs.run(synchronousCode, null, function(){
	console.log("finish");
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>