承诺和行动顺序

时间:2019-06-20 04:17:37

标签: javascript es6-promise

抱歉,如果这是一个基本概念。我是Java语言的新手。

我试图了解以下功能的执行顺序。我立即设置了带有2个回调的Promise和带有3个回调的Promise。

function getSum(n1, n2){
    var isAnyNegative = function() {
        return n1<0 || n2 < 0;
    }
    var promise = new Promise(function(resolve, reject) {
        if (isAnyNegative()){
            reject(Error('Negative not supported'));
        }
        resolve(n1 + n2)
    });
    return promise;
}

// Double Promise
getSum(5,6).then(function(result) {
  console.log('DL1 '+result);
  return getSum(10,20);
}, function(error){
  console.log(error);
}).then(function(result) {
  console.log('DL2 '+result);
}, function(error){
  console.log(error);
});

// Triple Promise
getSum(5,6).then(function(result) {
  console.log('TL1 '+result);
  return getSum(10,20);
}, function(error){
  console.log(error);
}).then(function(result){
  console.log('TL2 '+result);
  return getSum(30,40);
}, function(error){
  console.log(error);
}).then(function(result){
  console.log('TL3 ' +result);
}, function(error){
  console.log(error);
});

输出如下(DL =>双层,TL =>三层):

DL1 11
TL1 11
DL2 30
TL2 30
TL3 70

本来希望输出是双层然后是三层,但是事实并非如此。我研究了吊装,但据我了解,它至少应该保护脚本中的执行顺序。这些函数如何排序,为什么不按出现顺序执行?

如果需要更多详细信息,请先致歉,并提前致谢。

2 个答案:

答案 0 :(得分:1)

在运行诺言时,每个.then处理程序都按照https://javascript.info/microtask-queue的说明异步运行

基本上对于您的代码而言

  • 首先运行主要代码,DL1排队,TL1排队
  • 随着主要代码的执行结束,DL1排在队列中的第一位,因此它将执行并排队DL2
  • 当引擎以DL1完成时,它将接受下一个排队的项目; TL1,它执行TL2并排入队列。
  • 现在队列中的下一个项目是DL2,其余的TL紧随其后

如果您真的需要诺言先解决DL,然后是TL,则需要使它们成为同一诺言链的一部分

答案 1 :(得分:0)

示例中的执行顺序正确。

谈到异步操作(Promises),整个概念与同步操作有些不同。

在下面的说明中,您可以将Promise假定为运行操作的时间表/队列。

例如,使用以下简化代码:

function sum(a, b){
  return new Promise(function(resolve, reject){
    if (a < 0 || b < 0)
      reject(new Error('Negative not supported.'));
    else
      resolve(a + b);
  });
}


/* Double layer */
sum(5, 6).then(function(result){
  console.log('DL1', result);
  return sum(10, 20);
}).then(function(result){
  console.log('DL2', result);
}).catch(function(error){
  console.error(error);
});


/* Triple layer */
sum(5, 6).then(function(result){
  console.log('TL1', result);
  return sum(10, 20);
}).then(function(result){
  console.log('TL2', result);
  return sum(30, 40);
}).then(function(result){
  console.log('TL3', result);
}).catch(function(error){
  console.error(error);
});

如果我们遵循上面的示例,执行队列将类似于:

  1. 声明函数sum
  2. 将功能sum(5, 6)作为DL运行。
  3. 返回承诺(DL),sum(DL)的执行结束。
  4. 将功能sum(5, 6)作为TL运行。 Promise DL在后台运行。
  5. 返回承诺(TL),sum(TL)的执行结束。 Promise DL在后台解决。
  6. 运行DL1 .then()是因为在步骤5中解决了Promise DL。在后台解决了Promise TL。
  7. TL1 .then()之所以运行,是因为Promise TL在步骤6中得到了解决。DL1在后台得到了解决。
  8. 运行DL2 .then()是因为在步骤7中解决了Promise DL1。在后台解决了Promise TL1。
  9. ...(你明白了)

如您所见,使用Promises,一些操作在后台运行。这就是为什么您会看到执行顺序可能看起来不一样的原因。