Promise.all如何在数组和对象之间使用逗号运算符工作?

时间:2018-08-29 09:26:16

标签: javascript promise

我遇到了这段代码:

const results = await Promise.all(
                          [ Model1.find({}), Model2.find({}) ],
                          Model3.find({})
                      ),
        v1 = results[0],
        v2 = results[1],
        v3 = results[2]

正在使用一个数组和一个对象调用all(),而 Model *是猫鼬模型

这是一个易于修复的错误,但我想了解它如何赋予结果值:

  • v1保存与Model1对应的所有文档
  • v2保存与Model2对应的所有文档
  • v3为undefined

this answer on the comma operator中所述,我期望只有Model3.find({})承诺会实际返回results中的数据,因为逗号运算符应评估第一个操作数,但应返回其第二个操作数(到{ {1}})。而是相反:Promise.all()results[0]都包含数据,而results[1](因此results[2])是v3

我想念什么?

2 个答案:

答案 0 :(得分:3)

您的函数调用

Promise.all([ Model1.find({}), Model2.find({}) ], Model3.find({}))
//          ^-     First parameter            -^  ^- second    -^

您仅向Promise.all函数传递了两个承诺-

  1. 前两个作为数组-[Model1.find({}), Model2.find({})]
  2. 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