Promise.all (). Then () risolvere?


95

Utilizzando il nodo 4.x. Quando si dispone di un Promise.all(promises).then()qual è il modo corretto per risolvere i dati e passarli al successivo .then()?

Voglio fare qualcosa del genere:

Promise.all(promises).then(function(data){
  // Do something with the data here
}).then(function(data){
  // Do more stuff here
});

Ma non sono sicuro di come portare i dati al 2 ° .then(). Non posso usare resolve(...)il primo .then(). Ho capito che posso farlo:

return Promise.all(promises).then(function(data){
  // Do something with the data here
  return data;
}).then(function(data){
  // Do more stuff here
});

Ma questo non sembra il modo corretto per farlo ... Qual è l'approccio giusto a questo?

Risposte:


142

Ma questo non sembra il modo corretto per farlo ..

Questo è davvero il modo corretto per farlo (o almeno un modo corretto per farlo). Questo è un aspetto chiave delle promesse, sono una pipeline ei dati possono essere massaggiati dai vari gestori nella pipeline.

Esempio:

const promises = [
  new Promise(resolve => setTimeout(resolve, 0, 1)),
  new Promise(resolve => setTimeout(resolve, 0, 2))
];
Promise.all(promises)
  .then(data => {
    console.log("First handler", data);
    return data.map(entry => entry * 10);
  })
  .then(data => {
    console.log("Second handler", data);
  });

( catchgestore omesso per brevità. Nel codice di produzione, sempre propagare la promessa o gestire il rifiuto.)

L'output che vediamo da questo è:

Primo gestore [1,2]
Seconda mano [10,20]

... perché il primo gestore ottiene la risoluzione delle due promesse ( 1e 2) come un array, quindi crea un nuovo array con ciascuno di questi moltiplicato per 10 e lo restituisce. Il secondo gestore ottiene ciò che il primo gestore ha restituito.

Se il lavoro aggiuntivo che stai facendo è sincrono, puoi anche inserirlo nel primo gestore:

Esempio:

const promises = [
  new Promise(resolve => setTimeout(resolve, 0, 1)),
  new Promise(resolve => setTimeout(resolve, 0, 2))
];
Promise.all(promises)
  .then(data => {
    console.log("Initial data", data);
    data = data.map(entry => entry * 10);
    console.log("Updated data", data);
    return data;
  });

... ma se è asincrono non vorrai farlo poiché finisce per essere annidato e l'annidamento può sfuggire rapidamente di mano.


1
Interessante. Grazie. Quindi non è possibile rejectun valore dopo la Promisefunzione iniziale ? O il lancio di un errore in qualsiasi punto della catena ti porterà al .catch()? Se è così, qual è il punto rejectin primo luogo? Perché non lanciare semplicemente errori? Grazie ancora,
Jake Wilson

6
@ JakeWilson: Quelle sono domande diverse. Ma stai confondendo due cose separate: creare e saldare la promessa e gestire la promessa. Quando crei e stabilisci la promessa, usi resolvee reject. Quando gestisci , se l'elaborazione fallisce, in effetti lanci un'eccezione per attivare il percorso di errore. E sì, puoi anche lanciare un'eccezione dalla Promiserichiamata originale (invece di usare reject), ma non tutti gli errori sono eccezioni.
TJ Crowder

1

Oggi NodeJS supporta la nuova async/awaitsintassi. Questa è una sintassi semplice e rende la vita molto più facile

async function process(promises) { // must be an async function
    let x = await Promise.all(promises);  // now x will be an array
    x = x.map( tmp => tmp * 10);              // proccessing the data.
}

const promises = [
   new Promise(resolve => setTimeout(resolve, 0, 1)),
   new Promise(resolve => setTimeout(resolve, 0, 2))
];

process(promises)

Per saperne di più:


1
come posso passare i parametri a ogni singola promessa dal processo? @ Aminadav Glickshtein
bhaRATh

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.