У меня есть структура, подобная массиву, которая предоставляет асинхронные методы. Асинхронный метод вызывает структуры массива возврата, которые, в свою очередь, предоставляют больше асинхронных методов. Я создаю еще один объект JSON для хранения значений, полученных из этой структуры, поэтому мне нужно быть осторожным при отслеживании ссылок в обратных вызовах.
Я написал решение для грубой силы, но я хотел бы узнать более идиоматическое или чистое решение.
- Шаблон должен повторяться для n уровней вложенности.
- Мне нужно использовать обещание.all или какой-либо подобный метод, чтобы определить, когда разрешить процедуру включения.
- Не каждый элемент обязательно требует выполнения асинхронного вызова. Итак, во вложенном обещании я не могу просто назначать элементы массива JSON на основе индекса. Тем не менее мне нужно использовать что-то вроде обещания.all во вложенном forEach, чтобы гарантировать, что все присвоения свойств были выполнены до разрешения включающей подпрограммы.
- Я использую библиотеку обещаний bluebird, но это не требование
Вот частичный код -
var jsonItems = [];
items.forEach(function(item){
var jsonItem = {};
jsonItem.name = item.name;
item.getThings().then(function(things){
// or Promise.all(allItemGetThingCalls, function(things){
things.forEach(function(thing, index){
jsonItems[index].thingName = thing.name;
if(thing.type === 'file'){
thing.getFile().then(function(file){ //or promise.all?
jsonItems[index].filesize = file.getSize();
javascript
node.js
asynchronous
promise
user3205931
источник
источник
Promise.map
(одновременным) иPromise.each
(последовательным) в этом случае, также примечаниеPromise.defer
устарело - код в моем ответе показывает, как этого избежать, возвращая обещания. Обещания - это возвращаемые значения.Ответы:
Это довольно просто с некоторыми простыми правилами:
then
, возвращайте его - любое обещание, которое вы не вернете, не будет ожидаться снаружи..all
они - таким образом, ожидаются все обещания, и никакие ошибки ни в одном из них не заглушаются.then
s, вы обычно можете вернуться в середину -then
цепочки обычно не более 1 уровня в глубину.И несколько советов:
.map
чем сfor/push
- если вы сопоставляете значения с функцией,map
позволяет кратко выразить понятие применения действий по одному и агрегирования результатов.Promise.all
чем выполнять одно за другим - каждое ждет раньше другого.Итак, приступим:
источник
Вот простой пример использования reduce. Он работает последовательно, поддерживает порядок вставки и не требует Bluebird.
И используйте это так:
Мы сочли полезным отправить дополнительный контекст в цикл. Контекст не является обязательным и используется всеми итерациями.
Ваша функция обещания будет выглядеть так:
источник
У меня была такая же ситуация. Я решил использовать два Promise.All ().
Я считаю, что это действительно хорошее решение, поэтому я опубликовал его на npm: https://www.npmjs.com/package/promise-foreach
Я думаю, ваш код будет примерно таким
источник
Просто чтобы добавить к представленному решению, в моем случае я хотел получить несколько данных из Firebase для списка продуктов. Вот как я это сделал:
источник