Eu tenho uma estrutura parecida com uma matriz que expõe métodos assíncronos. As chamadas de método assíncrono retornam estruturas de matriz que, por sua vez, expõem mais métodos assíncronos. Estou criando outro objeto JSON para armazenar valores obtidos dessa estrutura e, portanto, preciso ter cuidado ao manter o controle de referências em retornos de chamada.
Codifiquei uma solução de força bruta, mas gostaria de aprender uma solução mais idiomática ou limpa.
- O padrão deve ser repetido para n níveis de aninhamento.
- Preciso usar a promessa.all ou alguma técnica semelhante para determinar quando resolver a rotina de fechamento.
- Nem todo elemento envolverá necessariamente fazer uma chamada assíncrona. Portanto, em uma promessa aninhada. Tudo que eu não posso simplesmente fazer atribuições aos meus elementos do array JSON com base no índice. No entanto, preciso usar algo como promessa.all no forEach aninhado para garantir que todas as atribuições de propriedade tenham sido feitas antes de resolver a rotina de fechamento.
- Estou usando a lib de promessa do bluebird, mas isso não é um requisito
Aqui está um código parcial -
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
fonte
fonte
Promise.map
(simultâneo) ePromise.each
(sequencial) neste caso, também observe quePromise.defer
está obsoleto - o código em minha resposta mostra como evitá-lo retornando promessas. As promessas têm tudo a ver com valores de retorno.Respostas:
É bastante direto com algumas regras simples:
then
, devolva-a - qualquer promessa que você não retornar não será esperada do lado de fora..all
elas - dessa forma, espera por todas as promessas e nenhum erro de qualquer uma delas é silenciado.then
s, normalmente pode retornar no meio - asthen
cadeias geralmente têm no máximo 1 nível de profundidade.E algumas dicas:
.map
que comfor/push
- se você estiver mapeando valores com uma função,map
permite expressar concisamente a noção de aplicar ações uma a uma e agregar os resultados.Promise.all
do que executar as coisas uma após a outra - cada uma esperando antes da próxima.Ok, então vamos começar:
fonte
Aqui está um exemplo simples usando reduzir. Ele é executado em série, mantém a ordem de inserção e não requer Bluebird.
E use-o assim:
Achamos útil enviar um contexto opcional para o loop. O contexto é opcional e compartilhado por todas as iterações.
Sua função de promessa seria semelhante a esta:
fonte
Eu passei pela mesma situação. Resolvi usando dois Promise.All ().
Acho que foi uma solução muito boa, então publiquei no npm: https://www.npmjs.com/package/promise-foreach
Acho que seu código será mais ou menos assim
fonte
Apenas para complementar a solução apresentada, no meu caso eu queria buscar vários dados do Firebase para uma lista de produtos. Aqui está como eu fiz:
fonte