Для недавнего проекта мне нужно было собрать много асинхронных данных для выполнения определенной задачи.
Поскольку все выборки были асинхронными операциями, мне казалось очевидным, что это было ошибкой:
Код будет ждать получения результата от getA() перед вызовом getB() и так далее, но поскольку нам не нужно a для получения b или c, это пустая трата времени. Мы хотим получить все необходимое как можно скорее!
Вот почему Promise.all([...]) существует. И если эта статья не является учебным пособием по этому поводу, скажем так, что она вызывает все обещания, указанные в массиве, и возвращает обещание, которое разрешается только тогда, когда все данные обещания разрешаются.
Что здесь интересно, так это то, что это не не ждать разрешения каждого промиса перед вызовом следующего, как в нашем предыдущем примере. Он запускает их все и дает нам возможность узнать, когда все будет готово (возвращая все результаты):
Объявление объекта и массива
Но мы можем спросить себя: «Что произойдет, если мы ожидаем промисов внутри массива или объявления объекта?»
Будет ли разрешение промисов работать как в первом последовательном примере или как в примере Promise.all([...])?
К сожалению, несмотря на то, что его легче читать, он превращается в последовательный код и, таким образом, отбрасывает почти все преимущества асинхронизма.
Проблемы с Promise.all()
Итак, нам нужно использовать Promise.all([...]) , но у меня возникают проблемы с этим решением, когда количество промисов увеличивается, например:
Только представьте, если бы константы и методы были названы не как a, b и getA(), getB(), а скорее как monthlyStatistics, filteredStatistics, обе (или даже больше) вызывали бы одну и ту же функцию возврата промисов getStats(start, end, filters).
Вероятность пропустить строчку или неверно истолковать прочитанное быстро возрастает. И это несмотря на потенциальную подсказку типа (из-за возможности похожего типа, как в предыдущем примере со статистикой).
Говоря о подсказках типов, если вы используете Typescript с текущей версией VSCode (1.58.2, когда я пишу это), вы заметите, что файл lib.es2015.promise.d.ts «только» набирает до 10 промисов внутри массива, переданного Promise.all([...]) (таким образом, несмотря на метод не имеет такого низкого ограничения), что приводит к ошибке типа, если вы пытаетесь получить результаты «кортежным способом», как в предыдущем примере кода.
Окончательное решение
Мое личное решение приблизить функцию, возвращающую обещание, и переменную/константу, внутри которой я хочу хранить возвращаемое значение, заключается в следующем:
«Разве это не запустит код промисов дважды?» Нет, не будет, потому что мы запускаем методы создания промисов только один раз, а затем дважды ждем результата промисов. Сначала в Promise.all([...]), который мы знаем, запустим весь код промисов «одновременно», а затем во второй раз в назначении объекта мы ожидаем для каждого результата последовательно, но поскольку все промисы уже разрешены, результаты доступны в памяти и почти сразу вернулся.
Если хотите убедиться в этом, не верьте моим словам (но мой код ;-)):
Вывод
Это не обширная документация, а напоминание самому себе, которое может быть (или не быть) полезным для других.
В этом отношении, пожалуйста, сообщите мне, если что-то не так, и не стесняйтесь делиться своими мыслями о конечном результате или о вашем собственном другом методе :-)
(Так как это мой первый пост на Medium в качестве человека, для которого английский язык не является родным, сообщите мне, если заметите опечатку или я нарушил секретное правило сообщества ;-))