Javascript 为什么承诺会在声明时执行?

Javascript 为什么承诺会在声明时执行?,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,我想使用Promise.all()执行一组承诺。我的方法是将这些承诺放在一个数组中,然后将该数组传递给Promise.all()。然而,我发现承诺一经声明就开始执行,甚至不需要等待Promise.all被调用 为什么会发生这种情况?我如何让承诺只在调用Promise.all()时执行 让promiseArray=[]; 常量值=[1,2,3,4,5]; 值。forEach((值)=>{ 承诺推送( 新承诺((解决、拒绝)=>{ console.log('value:'+value); 返回re

我想使用Promise.all()执行一组承诺。我的方法是将这些承诺放在一个数组中,然后将该数组传递给Promise.all()。然而,我发现承诺一经声明就开始执行,甚至不需要等待Promise.all被调用

为什么会发生这种情况?我如何让承诺只在调用Promise.all()时执行

让promiseArray=[];
常量值=[1,2,3,4,5];
值。forEach((值)=>{
承诺推送(
新承诺((解决、拒绝)=>{
console.log('value:'+value);
返回resolve();
})
)
})
console.log('start')
承诺。全部(承诺)
/*
输出为
价值:1
价值:2
价值:3
价值:4
价值:5
开始
本应预计产出会有所下降
开始
价值:1
价值:2
价值:3
价值:4
价值:5
*/
将承诺视为“执行”会让你感到困惑。承诺纯粹是一种通知机制。它通常与一些底层异步操作相关联,当您创建承诺时,异步操作通常会启动

Promise.all()
然后用于跟踪您已经开始的一系列异步操作何时完成(或以错误结束)

所以,你不能用
Promise.all()
来开始一系列的事情。您使用它只是为了跟踪它们何时全部完成,以及它们何时在代码的其他地方开始


使用
new promise()
手动创建承诺时,承诺执行者将立即执行。它们就是这样设计的

如果在promise executor中有真正的异步操作,并且在这些操作完成时正在执行
console.log()
,那么您可能不会发现promise的设计有任何问题。我认为您的大部分困惑源于这样一个事实,即您的承诺执行器中实际上没有任何异步操作,因此实际上没有理由为此使用承诺。承诺旨在跟踪异步操作的完成情况。如果没有实际的异步操作,就没有理由使用它们

仅供参考,如果您希望在将来某个时间从promise executor内部启动某些异步操作,您可以使用正常的
setTimeout()
process.nextTick()
setImmediate()
操作来计划稍后启动的操作

本应预计产出会有所下降


另外,您似乎希望输出的顺序严格
Promise.all()
期望有N个异步操作并行运行,并且没有保证这N个操作的完成顺序。相反,
Promise.all()
将跟踪所有结果,收集所有结果,并将
.then()
处理程序按顺序显示一组结果(如果它们都已成功解析)。它没有按顺序运行操作本身。这些操作以并行方式运行,并以任何自然顺序完成。

是的,承诺会立即执行。他们不能以任何其他方式工作。承诺,就像JS中的任何其他对象一样,完全不知道引用它们的是什么以及它们是如何传递的,所以它们无法“等待”,直到对它们的引用完成了特定的操作

您的解决方案是在将承诺传递给
Promise.all()时创建承诺:


而且,一旦你的承诺真的让事情变得不同步,它们就不一定会按照原来的顺序解决。要以正确的顺序获得结果,请使用
Promise.all(…).then()
,这是
Promise.all()

的全部目的,这就是它们的工作原理-承诺执行器立即同步执行。。。没有简单的答案来解释原因。如果您希望代码按照预期的方式运行,只需将代码更改为一行即可
promiseArray.push(()=>
然后
promiseArray.all(promiseArray.map(fn=>fn())
您的直觉实际上是合理的。急切地执行promiseArray构造函数的设计决策至少是有问题的。
[…]它们无法以任何其他方式工作。[…]
这不是真的,
新承诺
可能会延迟使用
setImmediate
传递给构造函数的回调的执行,然后
开始
将出现在
值:
输出之前。但这没有多大意义,因为承诺通常用于观察异步代码(参见的答案)@t.niese AFAIK,
setImmediate
不是标准的,它不会延迟承诺对执行者的调用,它只是意味着您将代码包装在单独的延迟中。这与承诺本身或其传递方式无关。“无法以任何其他方式工作”是指允诺能够根据引用它的变量的情况调用执行器的概念(在本例中传递给
promise.all()
)是的,
setImmediate
/
setTimeout
…不是语言规范的一部分,我只是用它作为说明。OP想知道为什么
start
显示在
value
之后。这种假设经常出现,因为承诺用于异步代码,而在NodeJ中,所有可能被称为异步的回调都应该是始终被称为异步(所有那些
err、value
callbacks)。因此,有些人期望传递给
new Promise
的回调也会像那些
err,value
回调一样被称为异步回调。Promise实现肯定可以做到这一点,但它没有意义。这让我大吃一惊!我对promises的思维模式一直是,它们都是“特殊”的函数“已解决”而不是“返回”母鸡
let promiseFnArray = [];
const values = [1, 2, 3, 4, 5];

values.forEach((value) => {
  promiseFnArray.push((resolve, reject) => {
    console.log('value: ' + value);
    return resolve();
  }))
})

console.log('start')
Promise.all(promiseFnArray.map(promiseFn => new Promise(promiseFn));