简体   繁体   English

如何链接返回承诺或价值的函数?

[英]How to chain functions returning promises or values?

I have an array of functions which I want to execute in order, some of those functions return a promise, while others simply return a value. 我有一个要按顺序执行的函数数组,其中一些函数返回promise,而其他一些则仅返回值。

I want the functions to be executed one at a time, in order they appear in the array. 我希望函数一次执行一次,以便它们出现在数组中。 If the function returns a promise, I want to wait until it resolves to a value. 如果函数返回一个Promise,我要等到它解析为一个值。 If it returns a value, I want it to simply use that value. 如果它返回一个值,我希望它简单地使用该值。

Example of how I want it to work: 我希望它如何工作的示例:

function f1() {
  return 1;
}
function f2() {
  return new Promise(function (resolve, reject) {
    // ...
    resolve(4);
  }).then(function (num) {return num / 2; });
}
function f3() {
  return Promise.resolve("3");
}
var array = [f1, f2, f3];

chain(array).then(function (values) {
    // values == [1, 2, "3"];
});

In case any of the promises fail, the chain function should stop execution and pass the error further. 万一任何承诺失败,链函数应停止执行并进一步传递错误。

Your current solution is pretty overkill, promises already accept values and/or promises with .then , you can refactor your code to this: 您当前的解决方案是过大的,promise已经接受了值和/或使用.then promise,您可以将代码重构为:

var queue = Promise.resolve(); // start empty queue
var results = arr.map(function(el){
   return (queue = queue.then(function(){ // update the queue to wait for next promise
       return el(); // call the function, return it so the array resolves to it 
   }));
});
Promise.all(results).then(function(results){
     // access all results here
});

Figured this out while making the question and decided to share. 在提出问题时想出了这一点,并决定分享。

function chain(array) {
  array = array.slice(); // Make a copy
  var result = [];
  return new Promise(function (resolve, reject) {
    (function chainLoop() { // Make an IIFE-based loop
      if (array.length > 0) {            // If we have elements in the array...
        Promise.resolve(array.shift()()) // Remove and resolve value of first element from the array
            .then(function (value) {
          result.push(value); // Push onto the result
          chainLoop(); // Loop - This won't cause a stack overflow, promises reset the stack
        }, reject);
      } else {           // Otherwise, if the array is empty...
        resolve(result); // resolve with our result array.
      }
    }());
  });
}

Usage: 用法:

chain([f1, f2, f3]).then(function (values) {
  console.log(values); // [1, 2, "3"] (assuming f1, f2, f3 from the question)
});

This will crash if there are non-functions in the array, so there is room for improvement, but this fits my needs so far. 如果阵列中没有功能,这将导致崩溃,因此仍有改进的空间,但这到目前为止满足了我的需求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM