Promise与遍历(轮回,无限多的then)碰到的题目及三个解决方案

本日遇到一个需要用Promise做无限轮回then的一个案例,马上脑洞大开。
事变是如许的,有如许的一群异步函数,

var func1 = function(callback){
    setTimeout(function(){
      console.log('foo');
      typeof(callback) !== 'function' || callback();
    }, 499);
};

var func2 = function(callback){
    setTimeout(function(){
      console.log('bar');
      typeof(callback) !== 'function' || callback();
    }, 500);
};

var func3 = function(callback){
    setTimeout(function(){
      console.log('foobar');
      typeof(callback) !== 'function' || callback();
    }, 501);
};
// ... more ...

将它们封装成Promise,顺次放入一个数组内:

// promisify those callback functions
var promisify = function(func){
  return function(){
    return new Promise(function(resolve){
      func(resolve);
    });
  }
}

// array can be infinitely long
var func_arr = [promisify(func1), promisify(func2), promisify(func3)];

需要让数组里的每个Promise顺次举行,末了一个实行完就完毕。
我的第一个主意是如许的:

// solution 1 failed
var master = [];

for (var i = 0; i < func_arr.length; i++) {
  master[i] = function(){
    if (i == 0) {
      return func_arr[i]();
    }
    else {
      return master[i-1]().then(function(){
        return func_arr[i]();
      })
    }
  };
};

master[master.length-1]();

乍看没有问题啊,每个新的master子函数的值是它上一个子函数的值加上一个then,然则一向报错——Maximum call stack size exceeded (node) / too much recursion (firefox)。
(12/24圣诞夜更新:已处理,修改了部份代码见下文)

僵了一会,照样谷哥协助了我,搜到一个异常简约的要领:

// solution 2 // success
func_arr.reduce(function(cur, next) {
    return cur.then(next);
}, Promise.resolve()).then(function() {
    console.log('job finished');
});

看得我腿都拍出坑了,实际上是我想庞杂了,没有必要在轮回里不断地返回闭包函数比及末了挪用,能够直接在轮回里挪用。
因而心有不甘,reduce()能完成的我大for岂有完成不了的原理,实则也不难,准确要领以下:

// solution 3 // success
var master = [];
master[0] = func_arr[0]();
for (var i = 1; i < func_arr.length; i++) {
  master[i] = master[i-1].then(func_arr[i]);
};

以下再供应一种反复挪用函数式(就是递归)的要领:

// solution 4 // success
function loop(i) {
  if (i != func_arr.length) {
    return func_arr[i]()
    .then(function() {
      return loop(i+1);
    });
  }
  return Promise.resolve(i);
}

loop(0).then(function(loop_times){
  console.log('job finished');
});

不知道人人另有没有更好的处理计划,或许能示知我第一个计划失足的缘由吧

================

12/24更新

谢谢wowhy的提醒,将我的solution 1的代码到场一层闭包,已处理了因表里函数变量发生的BUG:

// solution 1 // success now
var master = [];

for (var i = 0; i < func_arr.length; i++) {
  master[i] = (function(j){
    return function(){
      if (j == 0) {
        return func_arr[j]();
      }
      else {
        return master[j-1]().then(function(){
          return func_arr[j]();
        })
      }
    }
  })(i);
};

var execute = master[master.length-1];
execute();

乍看这一串代码很长,对照之前的计划显得完整过剩,在我看来,能够天生在外部其他的上下文内举行自力挪用的函数要更相符我大脑的头脑体式格局:)。

    原文作者:tomzhu
    原文地址: https://segmentfault.com/a/1190000004191366
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞