Promise.all (). Then () giải quyết?


95

Sử dụng Node 4.x. Khi bạn có một Promise.all(promises).then()cách thích hợp để giải quyết dữ liệu và chuyển nó cho người tiếp theo là .then()gì?

Tôi muốn làm một cái gì đó như thế này:

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

Nhưng tôi không chắc chắn làm thế nào để đưa dữ liệu đến thứ 2 .then(). Tôi không thể sử dụng resolve(...)trong lần đầu tiên .then(). Tôi đã tìm ra tôi có thể làm điều này:

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

Nhưng đó không phải là cách thích hợp để làm điều đó ... Cách tiếp cận đúng cho việc này là gì?

Câu trả lời:


142

Nhưng đó có vẻ không phải là cách thích hợp để làm điều đó ..

Đó thực sự là cách thích hợp để làm điều đó (hoặc ít nhất là một cách thích hợp để làm điều đó). Đây là khía cạnh quan trọng của lời hứa, chúng là một đường ống và dữ liệu có thể được xoa bóp bởi các trình xử lý khác nhau trong đường ống.

Thí dụ:

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

( catchBỏ qua trình xử lý để ngắn gọn. Trong mã sản xuất, luôn luôn tuyên truyền lời hứa hoặc xử lý từ chối.)

Kết quả mà chúng ta thấy từ đó là:

Xử lý đầu tiên [1,2]
Xử lý thứ hai [10,20]

... bởi vì trình xử lý đầu tiên nhận độ phân giải của hai lời hứa ( 12) dưới dạng một mảng, sau đó tạo một mảng mới với mỗi cái được nhân với 10 và trả về nó. Trình xử lý thứ hai nhận được những gì mà trình xử lý đầu tiên trả lại.

Nếu công việc bổ sung bạn đang làm là đồng bộ, bạn cũng có thể đặt nó vào trình xử lý đầu tiên:

Thí dụ:

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

... nhưng nếu nó không đồng bộ, bạn sẽ không muốn làm điều đó vì nó sẽ bị lồng vào nhau và việc lồng vào nhau có thể nhanh chóng vượt khỏi tầm tay.


1
Hấp dẫn. Cảm ơn bạn. Vì vậy, là nó không thể để rejectmột giá trị sau Promisehàm ban đầu ? Hay việc ném một lỗi vào bất kỳ đâu trong chuỗi sẽ đưa bạn đến .catch()? Nếu đúng như vậy thì điểm rejectđầu tiên là gì? Tại sao không chỉ ném lỗi? Cảm ơn một lần nữa,
Jake Wilson

6
@JakeWilson: Đó là những câu hỏi khác nhau. Nhưng bạn đang nhầm lẫn giữa hai điều riêng biệt: Tạo và giải quyết lời hứa và xử lý lời hứa. Khi bạn đang tạo và giải quyết lời hứa, bạn sử dụng resolvereject. Khi bạn đang xử lý , nếu quá trình xử lý của bạn không thành công, bạn thực sự ném ra một ngoại lệ để kích hoạt đường dẫn lỗi. Và có, bạn cũng có thể ném một ngoại lệ từ cuộc Promisegọi lại ban đầu (thay vì sử dụng reject), nhưng không phải tất cả các lỗi đều là ngoại lệ.
TJ Crowder

1

Hôm nay NodeJS hỗ trợ mới async/awaitcú pháp. Đây là một cú pháp dễ dàng và làm cho cuộc sống dễ dàng hơn nhiều

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)

Tìm hiểu thêm:


1
làm cách nào để chuyển các tham số cho từng lời hứa riêng lẻ từ quá trình? @ Aminadav Glickshtein
bhaRATh

1

return dataCách tiếp cận của bạn là đúng, đó là một ví dụ về chuỗi lời hứa . Nếu bạn trả lại một lời hứa từ lần .then()gọi lại của mình , JavaScript sẽ giải quyết lời hứa đó và chuyển dữ liệu cho lần then()gọi lại tiếp theo .

Chỉ cần cẩn thận và đảm bảo rằng bạn xử lý các lỗi với .catch(). Promise.all()từ chối ngay khi một trong các lời hứa trong mảng từ chối .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.