Chờ đợi trong Turn by Mistake


Bùi Trang Anh
1 năm trước
Hữu ích 5 Chia sẻ Viết bình luận 0
Đã xem 7084

Tôi thực sự thích làm việc với các hàm async mới, nhưng thực sự dễ dàng để thiết lập một tình huống trong đó mã có thể chạy song song buộc phải chạy theo trình tự. Hãy xem xét lời gọi đơn giản này của một hàm JavaScript có hai giá trị được trả về từ các hàm không đồng bộ khác:

const combination = await combine(await value(1), await value(2));


Vấn đề ở đây là trừ khi môi trường JS thực hiện một số tối ưu hóa cho bạn, các hành động có trong hai chờ đợi được thực hiện theo chuỗi.

function action() {
   return new Promise(resolve => {
       setTimeout(resolve, 5000)
   })
}

async function value(v) {
   console.log('started ' + v);
   return action('broken ' + v).then(()=> {
      console.log("finished " + v);
      return "ok "  + v
   })
}

async function test() {
 console.log(await value('1') + " " + await value('2'));
}
test();


Điều này sẽ dẫn đến một đầu ra trông giống như thế này (và sẽ mất khoảng 10 giây):

(index):39 started 1
(index):39 finished 1
(index):37 started 2
(index):39 finished 2
(index):44 ok 1 ok 2


Vì vậy, có một số cách để viết lại mã này để đảm bảo rằng tất cả các quy trình ban đầu được bắt đầu cùng một lúc. Tôi nghĩ rằng thứ hai là hình thức tốt nhất. Tôi chỉ ước họ đã đặt một số đường cú pháp để chúng tôi có thể loại bỏ các tài liệu tham khảo Promise.all.

async function test() {
  // Worst
  const three = value('3');
  const four = value('4');
  console.log(await three + " " + await four);

  // Better
  const [five, six] = await Promise.all([value('5'), value('6')]; 
  console.log(five + " " + six));

  // Better?
  console.log(...await Promise.all([value('7'), value('8')]))
}
test();


Vì vậy, bạn sẽ mong đợi một đầu ra thử nghiệm tương tự như thế này, với mỗi khối mất khoảng 5 giây tối thiểu.

(index):37 started 3
(index):37 started 4
(index):39 finished 3
(index):39 finished 4
(index):47 ok 3 ok 4
(index):37 started 5
(index):37 started 6
(index):39 finished 5
(index):39 finished 6
(index):48 ok 5 ok 6
(index):37 started 7
(index):37 started 8
(index):39 finished 7
(index):39 finished 8
(index):48 ok 7 ok 8


Ví dụ, thực sự dễ mắc lỗi tương tự khi viết vòng lặp for bằng cách đợi lần lượt từng mục

async function test() {

  const list = ['1', '2', '3'];
  const result = [];
  for (const item of list) {
     result.push(await value(item));
  }

  console.log(result);
}


Đối với hầu hết các hoạt động liên quan đến lời hứa và vòng lặp, thông thường bạn sẽ cần một bản đồ / Promise.all tại một số điểm. Phiên bản này sẽ hoàn thành trong khoảng 5 giây tối thiểu.

async function test() {

  const list = ['1', '2', '3'];
  const result = await Promise.all(list.map(value));

  console.log(result);
}


Hữu ích 5 Chia sẻ Viết bình luận 0
Đã xem 7084