Promise.all (). Then () resol?

96

Menggunakan Node 4.x. Ketika Anda memiliki cara Promise.all(promises).then()apa yang tepat untuk menyelesaikan data dan meneruskannya ke yang berikutnya .then()?

Saya ingin melakukan sesuatu seperti ini:

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

Tapi saya tidak yakin bagaimana cara mendapatkan data ke-2 .then(). Saya tidak bisa menggunakan resolve(...)yang pertama .then(). Saya tahu saya bisa melakukan ini:

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

Tapi sepertinya itu bukan cara yang tepat untuk melakukannya ... Apa pendekatan yang tepat untuk ini?

Jake Wilson
sumber

Jawaban:

143

Tapi sepertinya itu bukan cara yang tepat untuk melakukannya ..

Itu memang cara yang tepat untuk melakukannya (atau setidaknya sebuah cara yang tepat untuk melakukannya). Ini adalah aspek kunci dari promise, ini adalah pipeline, dan data dapat dipijat oleh berbagai penangan di pipeline.

Contoh:

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);
  });

( catchpenangan dihilangkan agar singkatnya. Dalam kode produksi, selalu sebarkan janji, atau tangani penolakan.)

Output yang kami lihat dari itu adalah:

Penangan pertama [1,2]
Penangan kedua [10,20]

... karena penangan pertama mendapatkan resolusi dari dua janji ( 1dan 2) sebagai larik, lalu membuat larik baru dengan masing-masing dikalikan dengan 10 dan mengembalikannya. Pawang kedua mendapatkan apa yang dikembalikan pawang pertama.

Jika pekerjaan tambahan yang Anda lakukan sinkron, Anda juga dapat meletakkannya di penangan pertama:

Contoh:

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;
  });

... tetapi jika asinkron, Anda tidak akan ingin melakukannya karena akhirnya menjadi bersarang, dan penumpukan dapat dengan cepat menjadi tidak terkendali.

TJ Crowder
sumber
1
Menarik. Terima kasih. Jadi, apakah tidak mungkin untuk rejectmendapatkan nilai setelah Promisefungsi awal ? Atau akankah melempar kesalahan di mana saja dalam rantai membawa Anda ke .catch()? Jika demikian, apa gunanya rejectsejak awal? Mengapa tidak membuang kesalahan saja? Terima kasih sekali lagi,
Jake Wilson
6
@JakeWilson: Itu adalah pertanyaan yang berbeda. Tapi Anda membingungkan dua hal yang berbeda: Membuat dan menepati janji, dan menangani janji. Saat Anda membuat dan menepati janji, Anda menggunakan resolvedan reject. Saat Anda menangani , jika pemrosesan Anda gagal, Anda memang membuat pengecualian untuk memicu jalur kegagalan. Dan ya, Anda juga bisa memunculkan pengecualian dari Promisecallback asli (daripada menggunakan reject), tetapi tidak semua kegagalan adalah pengecualian.
TJ Crowder
1

Saat ini NodeJS mendukung async/awaitsintaks baru . Ini adalah sintaks yang mudah dan membuat hidup lebih mudah

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)

Belajarlah lagi:

Aminadav Glickshtein
sumber
1
bagaimana cara mengirimkan parameter ke setiap janji individu dari proses? @ Aminadav Glickshtein
bhaRATh