Как работает Promise.all с оператором запятой между массивом и объектом? - PullRequest
0 голосов
/ 29 августа 2018

Я наткнулся на этот кусок кода:

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

, который вызывает all() с массивом и одним объектом & mdash; ` Модель * - это модели Mongoose .

Это легко исправляемая ошибка, но я бы хотел понять, как она дает результирующие значения:

  • v1 содержит все документы, соответствующие Model1
  • v2 содержит все документы, соответствующие Model2
  • v3 - undefined

Как объяснено в этом ответе на оператор запятой , я ожидал, что только Model3.find({}) обещает фактически вернуть данные в results, так как оператор запятой должен вычислять первый операнд, но возвращать свой второй операнд (до Promise.all()). Но вместо этого все наоборот: results[0] и results[1] оба содержат данные, в то время как results[2] (и, следовательно, v3) равно undefined.

Что мне не хватает?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Это список параметров , а не одно выражение, поэтому оператор запятой не применяется - массив

[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 принимает итерацию , а не Promise, поэтому вычисление оператора запятой:

await Promise.all((
  Model3.find({})
))

приведет к ошибке:

TypeError: undefined is not a function
0 голосов
/ 29 августа 2018

Ваш вызов функции

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

Вы передали только два обещания функции Promise.all -

  1. первые два в виде массива - [Model1.find({}), Model2.find({})].
  2. Model3 в качестве второго параметра - Model3.find({}).

Model3 передается, но игнорируется функцией - функция принимает только один параметр - первый, который должен быть повторяемым

Синтаксис

Promise.all(iterable);


Promise.all просто запускает те обещания, которые определены в первом параметре, и вы получаете только результаты для Model1.find({}) и Model2.find({}).

Вы думаете, что results[2] является результатом Model3.find({}), но это не так. В данном случае это массив, который содержит 2 элемента - результаты двух обещаний, которые передаются через array / iterable . Если вы хотите получить доступ к индексу массива, который больше length - 1, вы получите undefined.

Параметры функции

В JavaScript вы можете передать в функцию столько аргументов, сколько вам нужно, но параметры будут назначаться слева направо, а те аргументы, которые не вписываются в диапазон параметров, будут просто игнорироваться.

Посмотрите на приведенный ниже пример. Я передал 5 аргументов функции, но моя функция принимает только первые два, поэтому 3, 4, 5 просто игнорируются. У вас есть этот случай.

function foo(a, b) {
   console.log(a, b);
}

foo(1, 2, 3, 4, 5);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...