我遇到了这段代码:
const results = await Promise.all(
[ Model1.find({}), Model2.find({}) ],
Model3.find({})
),
v1 = results[0],
v2 = results[1],
v3 = results[2]
正在使用一个数组和一个对象调用all()
,而 Model *是猫鼬模型。
这是一个易于修复的错误,但我想了解它如何赋予结果值:
Model1
对应的所有文档Model2
对应的所有文档undefined
如this answer on the comma operator中所述,我期望只有Model3.find({})
承诺会实际返回results
中的数据,因为逗号运算符应评估第一个操作数,但应返回其第二个操作数(到{ {1}})。而是相反:Promise.all()
和results[0]
都包含数据,而results[1]
(因此results[2]
)是v3
。
我想念什么?
答案 0 :(得分:3)
您的函数调用
Promise.all([ Model1.find({}), Model2.find({}) ], Model3.find({}))
// ^- First parameter -^ ^- second -^
您仅向Promise.all函数传递了两个承诺-
[Model1.find({}), Model2.find({})]
。Model3
作为第二个参数-Model3.find({})
。 Model3
已通过,但被函数忽略-函数仅使用一个参数-第一个参数必须为 iterable
Promise.all(iterable);
Promise.all
只会运行第一个参数中定义的那些承诺,而您只会得到Model1.find({})
和Model2.find({})
的结果。
您认为results[2]
是Model3.find({})
的结果,但不是。在这种情况下,它是一个包含2个项目的数组-通过 array / iterable 传递的两个promise的结果。当您要访问大于length - 1
的数组索引时,将获得undefined
。
在JavaScript中,您可以传递给函数所需的参数,但是参数将从左到右分配,那些不适合参数范围的参数将被忽略。
看下面的例子。我已将5个参数传递给该函数,但是我的函数仅采用前两个参数,因此3, 4, 5
仅被忽略。你有这种情况。
function foo(a, b) {
console.log(a, b);
}
foo(1, 2, 3, 4, 5);
答案 1 :(得分:1)
那是一个参数列表而不是单个表达式,因此逗号运算符不适用-数组
[Model1.find({}), Model2.find({})]
被评估为传递给Promise.all
的第一个参数,第二个参数是
Model3.find({})
但是Promise.all
仅接受一个可迭代的参数; Model3
的第二个参数将被忽略,结果仅[Model1.find({}), Model2.find({})]
映射到其解析值。由于传递的数组只有两个值,因此Promise.all
解析为也只有两个值(索引[2]
为undefined
)的数组。
如果您将Promise.all
调用括在另一个括号中:
const results = await Promise.all((
[ Model1.find({}), Model2.find({}) ],
Model3.find({})
))
然后您将调用逗号运算符,因为在解释器尝试提出一个括号时,第二组括号内的所有内容都将被评估为单个表达式。传递给Promise.all
的第一个(也是唯一的)参数的值。 (但是Promise.all
接受 iterable ,而不是Promise
,因此对逗号运算符的求值是:
await Promise.all((
Model3.find({})
))
然后将导致错误:
TypeError: undefined is not a function