aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: await forEach không chờ các callback async

Suong Nguyen by Suong Nguyen
30/10/2026
in Phỏng vấn
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn thêm async vào callback của forEach rồi await cả lời gọi, nhưng đoạn code phía sau vẫn chạy trước khi công việc trong callback xong. Vấn đề không nằm ở việc máy chạy quá nhanh. forEach không gom những Promise callback trả về thành một Promise đại diện cho cả lượt xử lý.

Bài đối chiếu JavaScript documentation ngày 30/10/2026 và chạy ví dụ bằng Node.js 24.18.1. Fixture dùng một gate Promise do chính code mở, không dùng mạng hoặc suy đoán thứ tự dựa vào số mili giây của timer. Kết quả chỉ chứng minh cơ chế chờ, không đo khả năng xử lý song song của hệ thống thật.

Đọc giá trị forEach thực sự trả về

Array.forEach reference ghi rằng callback được mong đợi là đồng bộ và forEach không chờ Promise. Async function vẫn tạo Promise, nhưng API gọi callback có sử dụng Promise đó hay không là một câu hỏi riêng.

Đoạn dưới giữ các callback ở gate để ta quan sát được điểm forEach đã kết thúc mà không dựa vào tốc độ thiết bị:

async function showForEach() {
  const events = [];
  let release;
  const gate = new Promise(resolve => { release = resolve; });
  const pending = [];

  const returned = [1, 2].forEach(async id => {
    const task = (async () => {
      await gate;
      events.push(`done:${id}`);
    })();
    pending.push(task);
    await task;
  });

  await returned;
  events.push('after-forEach');
  console.log(returned === undefined);
  console.log(events.join(','));

  release();
  await Promise.all(pending);
  console.log(events.join(','));
}

showForEach().catch(console.error);

Kết quả là true, after-forEach, rồi after-forEach,done:1,done:2. Phần Promise.all trong fixture chỉ để dọn và chờ các task đã lưu sau khi mở gate; nó không phải hành vi forEach tự cung cấp.

await returned đang await undefined nên không tạo liên kết chờ với task. Callback async vẫn có Promise riêng, nhưng giá trị trả về của callback bị forEach bỏ qua. Async function reference giúp phân biệt Promise của function với cách bên gọi sử dụng nó.

Cần tuần tự thì await trong vòng lặp

Giả sử kết quả sau phụ thuộc bước trước hoặc bạn muốn dừng trước khi bắt đầu phần tử kế tiếp nếu có lỗi:

async function runSequential(items, save) {
  const results = [];
  for (const item of items) {
    results.push(await save(item));
  }
  return results;
}

runSequential([1, 2], async id => `saved:${id}`)
  .then(values => console.log(values.join(',')));

Ví dụ in saved:1,saved:2. Mỗi lời gọi save tiếp theo chỉ bắt đầu sau khi lời gọi trước hoàn tất. Khi save reject, hàm reject và vòng lặp không bắt đầu các phần tử còn lại, trừ khi bạn thêm cơ chế xử lý lỗi riêng.

for…of reference mô tả vòng lặp trên iterable. Điểm quan trọng trong code này là await nằm ngay trong thân vòng lặp của async function, không bị giấu trong callback của một API không chờ nó.

Công việc độc lập thì gom Promise có chủ đích

async function runTogether(items, save) {
  return Promise.all(items.map(item => save(item)));
}

runTogether([1, 2], async id => `saved:${id}`)
  .then(values => console.log(values.join(',')));

Code cũng trả saved:1,saved:2, nhưng hợp đồng bắt đầu công việc khác: map gọi save cho các phần tử để tạo danh sách Promise trước khi chờ cả nhóm. Thứ tự mảng kết quả tương ứng input không chứng minh các tác vụ hoàn tất theo thứ tự đó.

Không dùng map trên một danh sách khổng lồ rồi coi đây là bộ giới hạn concurrency. Nếu API có hạn mức hoặc tác vụ tốn tài nguyên, cần một cơ chế giới hạn riêng. Promise.all cũng không tự rollback những tác vụ đã ghi thành công.

Đặt kiểm tra lỗi ở đúng nơi

Một try/catch quanh await items.forEach(async ...) không tự bắt rejection xảy ra sau await bên trong callback. Để code gọi nhận được lỗi, phải return hoặc await một Promise thực sự đại diện cho công việc. Đừng chạy ca rejection không được quản lý chỉ để thử trên ứng dụng đang chạy.

Với runSequential, có thể dùng một save giả reject ở ID 2 và ghi lại ID đã bắt đầu để kiểm tra phần tử 3 chưa chạy. Với runTogether, quản lý các Promise theo hợp đồng của nhóm và xác định cần dừng phản hồi, thu đủ lỗi hay phục hồi phần nào. Bài không gọi API thật hoặc tạo side effect bên ngoài.

Lỗi thường gặp khi giải thích

  • Nói async bị forEach “vô hiệu hóa”; callback vẫn async, chỉ có bên gọi không chờ.
  • Thêm await trước forEach mà không đọc giá trị trả về.
  • Dựa vào setTimeout để đoán mọi thứ tự thực thi thay vì kiểm soát fixture.
  • Chọn chạy đồng thời chỉ vì cú pháp ngắn, bỏ qua dependency giữa các tác vụ.

Khi review, hỏi Promise nào đại diện cho toàn bộ công việc và ai đang await Promise đó. Câu hỏi này giúp chọn vòng lặp đúng, xử lý lỗi đúng và giải thích được vì sao code phía sau được phép tiếp tục.

Nguồn tham khảo

  • MDN: Array.prototype.forEach
  • MDN: async function
  • MDN: for…of

Tags: Async AwaitJavaScriptPhỏng vấn
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: vì sao tách method thành callback lại mất this?

by Suong Nguyen
29/10/2026
0

Theo dõi cách gọi method, callback độc lập, bind và arrow wrapper bằng ví dụ đồng bộ trong strict mode.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: vì sao callback trong vòng lặp đều đọc cùng giá trị?

by Suong Nguyen
28/10/2026
0

Tách vấn đề closure khỏi timer bằng các callback gọi sau vòng lặp, rồi so var, let và hàm tạo binding riêng.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Phỏng vấn JavaScript: Object.is khác === thế nào với NaN, +0 và -0?

by Suong Nguyen
27/10/2026
0

Giải thích hai khác biệt về số của Object.is và ===, kiểm tra object identity và tránh nhầm Object.is với so sánh sâu.

Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

JavaScript sort: vì sao số 10 đứng trước 2 và mảng gốc bị đổi?

by Suong Nguyen
26/10/2026
0

Kiểm tra thứ tự mặc định, hợp đồng comparator, tính ổn định và cách dùng toSorted để giữ mảng gốc khi sắp xếp.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native RefreshControl: giữ refreshing đúng vòng đời của lượt tải
  • Phỏng vấn JavaScript: await forEach không chờ các callback async
  • Android ACTION_VIEW: mở liên kết HTTPS và xử lý khi không có app nhận

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply