Я хотел бы прояснить этот момент, так как документация не слишком ясна по этому поводу;
Q1:Promise.all(iterable)
выполняется ли обработка всех обещаний последовательно или параллельно? Или, более конкретно, это эквивалент выполнения цепных обещаний, таких как
p1.then(p2).then(p3).then(p4).then(p5)....
или это какой - то другой вид алгоритма , где все p1
, p2
, p3
, p4
, p5
и т.д. называют одновременно (параллельно) и результаты возвращаются , как только все решимостью (или одного брака)?
Q2: Если Promise.all
работает параллельно, есть ли удобный способ запустить итерацию последовательно?
Примечание : я не хочу использовать Q или Bluebird, но все нативные спецификации ES6.
javascript
node.js
promise
es6-promise
Яник Рошон
источник
источник
Promise.all
выполняет их параллельно.node.js
и такio.js
как это, где я использую это. Так что, да, реализация V8, если хотите.Promise.all
.new Promise(a).then(b); c();
выполняется первым, а затем с, то б. Это не Promise.all, который выполняет эти обещания, он просто обрабатывает, когда они разрешаются.Ответы:
Нет, обещания не могут быть «выполнены». Они начинают свою задачу, когда они создаются - они представляют только результаты - и вы выполняете все параллельно, даже прежде чем передать их
Promise.all
.Promise.all
ждет только нескольких обещаний. Не имеет значения, в каком порядке они решаются или вычисления выполняются параллельно.Если у вас уже есть свои обещания, вы ничего не можете сделать, но
Promise.all([p1, p2, p3, …])
(который не имеет понятия последовательности). Но если у вас есть итеративные асинхронные функции, вы действительно можете запускать их последовательно. В основном вам нужно получить отв
и решение для этого использует
Array::reduce
:источник
then
последовательность - возвращаемое значение является обещанием для последнегоfn
результата, и вы можете связать другие обратные вызовы с этим.fn1().then(p2).then(fn3).catch(…
? Не нужно использовать выражение функции.retValFromF1
это передаетсяp2
, это именно то, чтоp2
делает. Конечно, если вы хотите сделать больше (передать дополнительные переменные, вызвать несколько функций и т. Д.), Вам нужно использовать выражение функции, хотя изменениеp2
в массиве будет прощеiterable
это[fn1, fn2, fn3, …]
массивВ параллели
Преимущества: быстрее. Все итерации будут выполнены, даже если одна не удалась.
В последовательности
Преимущества: переменные в цикле могут быть общими для каждой итерации. Ведет себя как обычный императивный синхронный код.
источник
for (const item of items) await fetchItem(item);
await Promise.all(items.map(async item => { return await fetchItem(item).catch(e => e) }))
async
функция является вызовом API и вы не хотите DDOS сервера. Вы лучше контролируете отдельные результаты и ошибки, возникающие при выполнении. Более того, вы можете решить, какие ошибки продолжать и что прерывать цикл.Ответ Bergis вывел меня на правильный путь, используя Array.reduce.
Однако, чтобы на самом деле получить функции, возвращающие мои обещания, выполняемые один за другим, мне пришлось добавить еще несколько вложений.
Мой реальный вариант использования - это массив файлов, которые мне нужно передавать по порядку один за другим из-за ограничений в нисходящем направлении ...
Вот чем я закончил.
Как предлагают предыдущие ответы, используя:
не дождался завершения передачи, прежде чем начать другую, а также текст «Все файлы передан» появился еще до начала первой передачи файла.
Не уверен, что я сделал не так, но хотел поделиться тем, что сработало для меня.
Изменить: так как я написал этот пост, я теперь понимаю, почему первая версия не работает. then () ожидает функцию, возвращающую обещание. Итак, вы должны передать имя функции без скобок! Теперь моей функции нужен аргумент, поэтому мне нужно добавить анонимную функцию без аргументов!
источник
просто чтобы уточнить ответ @ Bergi (что очень лаконично, но сложно понять;)
Этот код будет запускать каждый элемент в массиве и добавлять следующую «цепочку» в конец;
надеюсь, что это имеет смысл.
источник
Вы также можете последовательно обработать итерацию с помощью асинхронной функции, используя рекурсивную функцию. Например, заданный массив
a
для обработки с асинхронной функциейsomeAsyncFunction()
:источник
array.prototype.reduce
намного лучше с точки зрения производительности, чем рекурсивная функцияreduce
где вы должны построить всюthen()
цепочку за один шаг, а затем выполнить.NodeJS не выполняет обещания параллельно, он запускает их одновременно, поскольку это однопоточная архитектура цикла обработки событий. Существует возможность запустить вещи параллельно, создав новый дочерний процесс, чтобы использовать преимущества многоядерного процессора.
Параллельный против Concurent
Фактически, что
Promise.all
происходит, складывая функцию обещаний в соответствующей очереди (см. Архитектуру цикла событий), одновременно выполняя их (вызывая P1, P2, ...), затем ожидая каждого результата, затем разрешая Promise.all со всеми обещаниями полученные результаты. Promise.all потерпит неудачу при первом неисполнении обещания, если вы сами не справитесь с отклонением.Существует большое различие между параллельным и параллельным: первый будет запускать разные вычисления в отдельном процессе в одно и то же время, и они будут выполняться там же, в то время как другой будет выполнять разные вычисления один за другим, не дожидаясь предыдущего вычисления, чтобы закончить и прогрессировать одновременно, не завися друг от друга.
Наконец, чтобы ответить на ваш вопрос,
Promise.all
не будем выполнять ни параллельно, ни последовательно, а одновременно.источник
Использование асинхронного ожидания массива обещаний может быть легко выполнено последовательно:
Примечание. В приведенной выше реализации, если обещание отклонено, остальное не будет выполнено. Если вы хотите, чтобы все ваши обещания были выполнены, оберните
await a[i]();
внутреннюю частьtry catch
источник
параллельно
увидеть этот пример
запустив код, он утешит «ВЫЗОВ» для всех шести обещаний, а когда они будут решены, он будет утешать каждые 6 ответов после тайм-аута одновременно
источник
Ответ Берги помог мне сделать вызов синхронным. Я добавил ниже пример, где мы вызываем каждую функцию после вызова предыдущей функции.
источник
Вы можете сделать это за цикл.
Асинхронная функция возвращает обещание
если вы пишете следующий код, то клиент создается параллельно
тогда все клиенты создаются параллельно. но если вы хотите создать клиент последовательно, то вы должны использовать для цикла
тогда все клиенты создаются последовательно.
счастливого кодирования :)
источник
async
/await
доступен только с транспортером или с использованием других двигателей, кроме Node. Кроме того, вы действительно не должны смешиватьсяasync
сyield
. В то время как они действуют одинаково с транспортерамиco
, они действительно совершенно разные и не должны обычно заменять друг друга. Кроме того, вы должны упомянуть эти ограничения, так как ваш ответ вводит в заблуждение начинающих программистов.Я использовал для того, чтобы решить последовательные обещания. Я не уверен, поможет ли это здесь, но это то, чем я занимался.
источник
это может ответить на часть вашего вопроса.
да, вы можете связать массив функций, возвращающих обещание, следующим образом ... (это передает результат каждой функции следующей). Вы можете, конечно, отредактировать его, чтобы передать один и тот же аргумент (или без аргументов) каждой функции.
источник
Я наткнулся на эту страницу, пытаясь решить проблему в NodeJS: повторную сборку файловых блоков. В основном: у меня есть массив имен файлов. Мне нужно добавить все эти файлы в правильном порядке, чтобы создать один большой файл. Я должен сделать это асинхронно.
Модуль Node 'fs' предоставляет appendFileSync, но я не хотел блокировать сервер во время этой операции. Я хотел использовать модуль fs.promises и найти способ связать все это вместе. Примеры на этой странице мне не помогли, потому что на самом деле мне потребовалось две операции: fsPromises.read () для чтения в чанке файла и fsPromises.appendFile () для конкатенации в файл назначения. Возможно, если бы я был лучше с javascript, я мог бы заставить предыдущие ответы работать на меня. ;-)
Я наткнулся на это ... https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/ ... и я смог взломать рабочее решение.
TLDR:
И вот жасмин юнит-тест для него:
Надеюсь, это кому-нибудь поможет.
источник