为什么 Promise.all(array) 没有立即解决
Why the Promise.all(array) not resolved immediately?
我在机器上运行下面的代码示例(安装了 Node 5.8.0)并获得下一个结果(请参阅代码示例后面)。
代码示例:
'use strict'
var p1 = Promise.resolve();
var p2 = Promise.resolve();
var p12 = Promise.all([p1, p2]);
var cb = function() {
console.log(p12);
}
setTimeout(cb, 0);
console.log(p1);
console.log(p2);
console.log(p12);
结果:
承诺 { 未定义 }
承诺 { 未定义 }
承诺 { <pending>
}
承诺 { [ 未定义, 未定义 ] }
之后没有立即解析(在程序开始时解决 p1 和 p1),为什么"超时"p12 被解析了?解决 Promise.all(array) 是否需要一些时间?
根据承诺规范,在事件循环完成其当前周期后,始终异步调用承诺履行或拒绝处理程序。 因此,即使对它的论据都是已解决的承诺,p12
也不会立即解决。 因此,直到此事件循环完成后不久才会解决。这就解释了为什么你的第一句话:
console.log(p12);
表明承诺仍处于"悬而未决"状态。 它当前.then()
处理程序(如果有)尚未调用。 但是,一旦当前代码线程完成执行并且控制权返回到事件队列中的下一个事件,承诺将被解析,因此您的setTimeout()
认为它已解决。
这样做是出于调用方一致性的原因,以便无论承诺是否已解析还是尚未解析,.then()
都以异步方式一致地调用处理程序。 这允许调用代码始终一致地编码,而不必担心承诺是否已解决。 在所有情况下.then()
处理程序都是在当前堆栈展开并完成之后调用的。
根据承诺/A+ 规范:
在执行之前不得调用 onFulfilling 或 onReject 上下文堆栈仅包含平台代码。
这里的"平台代码"意味着引擎、环境和承诺 实现代码。在实践中,这一要求确保了 onFulfilled 和 onReject 在事件发生后异步执行 循环转弯,然后调用,并带有新的堆栈。这可以是 使用"宏任务"机制(如 setTimeout 或 set即时,或使用"微任务"机制,例如 MutationObserver 或 process.nextTick.自承诺实施以来 被认为是平台代码,它本身可能包含任务调度 队列或"蹦床",其中调用处理程序。
因此,所有这一切的结果是,承诺总是在当前执行线程完成后异步解析。 虽然内部细节可能比这复杂一些(可能涉及微任务),但从逻辑上讲,你可以通过将一条消息发布到事件队列来考虑一个承诺,它现在正在等待被解决/拒绝。 而且,每当事件队列完成当前正在运行的内容并轮到运行承诺.then()
处理程序时,它们才会执行。
- 使用promise和mongoose对文档进行排序
- 如何解决Yii中的页面刷新问题
- 测试Angular Service解决错误回调中的promise
- 节点协同与生成器和Promise并行流量控制
- 如何解决Access Control Allow Origin错误
- 在ES6 Promise中,我应该在解决/拒绝之前使用return吗
- AngularJS promise在加载数据之前得到解决
- addAssociation上的Promise是用源代码的陈旧版本解决的
- 为什么 Promise.all(array) 没有立即解决
- 承诺的解决顺序是否与Promise.sexel中提到的顺序相同
- AngularJS/Karma-测试函数返回已解决或拒绝的promise
- promise甚至在调用.resolve()之前就得到了解决
- Selenium Webdriver JavaScript: Promise似乎没有得到解决
- new Promise和Promise的区别.在bluebird中解决/拒绝
- Reactjs的render()在promise解决这个问题后不会被触发.setState被重新分配
- 在promise解决后解析值
- WebCrypto:Safari无法导出密钥(),并且promise似乎永远不会解决/失败
- deffered对象如何通知其promise它已被解决
- JavaScript Promise在解决问题时陷入困境
- 只保留解决并忽略被拒绝的promise中的值