Vòng lặp và promise

Vòng lặp với Promise

Chúng ta sẽ sử dụng với promise bao gồm vòng lặp for, forEachmap.

Trong ví dụ sau chúng ta sẽ tính tổng giá các loại trái cây. Đầu tiên là cài đặt các hàm sleep(), danh sách trái cây và lấy giá một trái cây sẽ mất một khoảng thời gian (trả về Promise).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// hàm sleep sẽ ngủ một thời gian sẽ chạy, trả về Promise
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

// danh sách trái cây và giá
var fruitPrices = {
  Apple: 27,
  Grape: 12,
  Pear: 14
};
var fruits = ['Apple', 'Grape', 'Pear'];

// hàm lấy giá sẽ ngủ 100ms mới lấy được giá của trái cây
const getNumFruit = fruit => {
  return sleep(100).then(v => fruitPrices[fruit]);
}

Tiếp theo chúng ta sẽ viết hàm lấy tổng giá dùng vòng lặp for.

1
2
3
4
5
6
7
8
9
// lặp các loại trái cây, cộng vào tổng giá
async function totalPrice() {
  var total = 0;
  for (let i = 0; i < fruits.length; i++) {
    total += await getNumFruit(fruits[i]);
  }
  return total;
}
totalPrice().then(total => console.log(total)); // 53

Sử dụng hàm forEach()

Hàm forEach sẽ không ra kết quả như mong đợi, vậy nên không nên dùng hàm forEach với await. Các promise sẽ chạy đồng thời nhưng chúng ta sẽ không lấy được kết quả.

1
2
3
4
5
6
7
8
9
// lặp các loại trái cây, cộng vào tổng giá
async function totalPrice() {
  var total = 0;
  fruits.forEach(async fruit => {
    total += await getNumFruit(fruit);
  });
  return total;
}
totalPrice().then(total => console.log(total)); // 0

Sử dụng với hàm map()

Sử dụng hàm map() thì sử dụng sẽ trả về danh sách các Promise. Chúng ta có thể sử dụng Promise.all() để chạy đồng thời các Promise này để lấy kết quả. Khác với vòng for đầu tiên, trong hàm này các Promise sẽ chạy đồng thời.

Các hàm filter(), hay reduce() có thể được sử dụng trong hàm Promise.all.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// lặp các loại trái cây, cộng vào tổng giá
async function totalPrice() {
  // lấy danh sách các promise
  var promises = fruits.map(async fruit => {
    return await getNumFruit(fruit);
  });

  // chạy các promise đồng thời, sau đó lấy tổng các kết quả
  var total = await Promise.all(promises)
    .then(results => results.reduce((s, a) => s + a, 0));
  
  return total;
}
totalPrice().then(total => console.log(total)); // 53