循环链顺序的Javascript承诺失败

时间:2018-09-14 03:49:24

标签: javascript loops promise

我尝试测试javascript Promise循环链,但失败了,我希望的Promise循环未排序,我的示例是这样的(1个设置超时,3个Promise函数):

//timeout
timeout = function (fn, pkg) {
    var t = setTimeout(function () {
        fn(pkg);
        clearTimeout(t);
    }, 1000);
};
//Promise function
p01 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P01';
        timeout(RS, echo);
    });
};
p02 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P02';
        timeout(RS, echo);
    });
};
p03 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P03';
        timeout(RS, echo);
    });
};

//do for loop test
for (var i = 0; i < 3; i++) {
    p01().then(function (echo) {
        console.log(echo);
        return p02();
    }).then(function (echo) {
        console.log(echo);
        return p03();
    }).then(function (echo) {
        console.log(echo);
        console.log('Done!');
    });
};

循环完成后,日志向我显示:

(3)Run P01
(3)Run P02
Run P03
Done!
Run P03
Done!
Run P03
Done!

我不知道发生了什么错误,如何解决该问题:

Run P01
Run P02
Run P03
Done!
Run P01
Run P02
Run P03
Done!
Run P01
Run P02
Run P03
Done!

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

当前,for循环中的每个迭代都同步地运行。 Promise链被初始化,但是在进行下一次迭代(并初始化另一个Promise链)之前,您不必等待它解决。

在每次迭代中将循环放入async函数中,并将await插入Promise链中(这样,直到当前迭代完全结束后,下一个迭代才开始):

//timeout
timeout = function(fn, pkg) {
  var t = setTimeout(function() {
    fn(pkg);
    clearTimeout(t);
  }, 1000);
};
//Promise function
p01 = function(check) {
  return new Promise(function(RS, RJ) {
    var echo = 'Run P01';
    timeout(RS, echo);
  });
};
p02 = function(check) {
  return new Promise(function(RS, RJ) {
    var echo = 'Run P02';
    timeout(RS, echo);
  });
};
p03 = function(check) {
  return new Promise(function(RS, RJ) {
    var echo = 'Run P03';
    timeout(RS, echo);
  });
};

//do for loop test

(async () => {
  for (var i = 0; i < 3; i++) {
    await p01().then(function(echo) {
      console.log(echo);
      return p02();
    }).then(function(echo) {
      console.log(echo);
      return p03();
    }).then(function(echo) {
      console.log(echo);
      console.log('Done!');
    });
  }
})();

或者有一个外部承诺,您每次都重新分配并致电.then

//timeout
timeout = function (fn, pkg) {
    var t = setTimeout(function () {
        fn(pkg);
        clearTimeout(t);
    }, 1000);
};
//Promise function
p01 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P01';
        timeout(RS, echo);
    });
};
p02 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P02';
        timeout(RS, echo);
    });
};
p03 = function (check) {
    return new Promise(function (RS, RJ) {
        var echo = 'Run P03';
        timeout(RS, echo);
    });
};

//do for loop test
let prom = Promise.resolve();
for (var i = 0; i < 3; i++) {
    prom = prom.then(p01).then(function (echo) {
        console.log(echo);
        return p02();
    }).then(function (echo) {
        console.log(echo);
        return p03();
    }).then(function (echo) {
        console.log(echo);
        console.log('Done!');
    });
};