Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Câu lệnh for await...of trong JavaScript

for await...of (ES2018) lặp qua async iterable — object implement Symbol.asyncIterator. Dùng để xử lý luồng dữ liệu bất đồng bộ (stream, pagination, real-time).

Cú pháp

for await (const item of asyncIterable) {
  // item là giá trị resolved từ Promise
}

Ví dụ 1: Lặp mảng thường (sync) trong async function

<script>
  const arr = [1, 2, 3, 4, 5];
  
  async function test() {
    for await (const num of arr) {
      document.write(num + '<br>');
    }
  }
  test();
</script>

Kết quả

1
2
3
4
5

Ví dụ 2: Custom Async Iterable (Symbol.asyncIterator)

<script>
  const asyncIterable = {
    [Symbol.asyncIterator]() {
      let i = 1;
      return {
        next() {
          if (i < 6) {
            // Trả về Promise resolve {value, done}
            return Promise.resolve({ value: i++, done: false });
          }
          return Promise.resolve({ done: true });
        }
      };
    }
  };

  async function consume() {
    for await (const num of asyncIterable) {
      document.write(num + '<br>');
    }
  }
  consume();
</script>

Kết quả

1
2
3
4
5

Thực tế: Async Generator Function (Dễ hơn)

async function* generateNumbers() {
  for (let i = 1; i <= 5; i++) {
    await new Promise(r => setTimeout(r, 100)); // Giả lập async delay
    yield i;
  }
}

async function main() {
  for await (const num of generateNumbers()) {
    console.log(num); // In 1..5 mỗi 100ms
  }
}
main();

Use Case Thực Tế

  • Stream processing: ReadableStream, fetch body (for await (const chunk of response.body)).
  • Pagination API: Async iterator tự động fetch page tiếp theo.
  • Database cursor: Lặp qua kết quả query lớn không load hết vào RAM.
  • WebSocket/EventSource: Wrapper async iterator cho message stream.

Lưu ý

  • Chỉ dùng trong async function hoặc module top-level (ES2022).
  • Nếu async iterable throw/reject → loop throw, cần try/catch.
  • break, continue, return hoạt động bình thường.
  • Parallel processing: dùng Promise.all với map thay vì for await (sequential).

So sánh

LoopIterableItem typeDùng cho
for...ofSync (Symbol.iterator)ValueArray, Map, Set, String...
for await...ofAsync (Symbol.asyncIterator)Resolved valueStream, async generator, paginated API