JavaScript - Lặp đồng bộ
Xin chào, những pháp sư JavaScript tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới của lặp đồng bộ. Đừng lo lắng nếu những từ ngữ này听起来 có vẻ đáng sợ - vào cuối bài học này, bạn sẽ tự tin sử dụng những khái niệm mạnh mẽ này như một chuyên gia. Vậy, chúng ta cùng bắt đầu nhé!
Lặp đồng bộ
Lặp đồng bộ là gì?
Hãy tưởng tượng bạn đang ở một quán cà phê đông đúc. Bạn đặt订单, nhưng thay vì chờ đợi tại quầy, bạn ngồi xuống và trò chuyện với bạn bè trong khi cà phê của bạn đang được chuẩn bị. Đó chính là những gì các thao tác đồng bộ trong lập trình - bạn bắt đầu một nhiệm vụ và sau đó chuyển sang làm những việc khác trong khi chờ đợi nó hoàn thành.
Lặp đồng bộcarry này một bước tiến xa hơn. Nó giống như nếu bạn đã đặt nhiều订单 cà phê, và mỗi ly cà phê sẽ được mang đến cho bạn ngay khi nó sẵn sàng, mà không cần bạn phải liên tục kiểm tra lại quầy.
Trong JavaScript, lặp đồng bộ cho phép chúng ta làm việc với các nguồn dữ liệu đồng bộ một cách tự nhiên và tuần tự, ngay cả khi các thao tác đang diễn ra trong nền.
Hiểu về các thao tác đồng bộ
Trước khi chúng ta nhảy vào lặp đồng bộ, hãy hiểu trước về các thao tác đồng bộ trong JavaScript.
Promises: Những nền tảng cơ bản
Promises là một khái niệm cơ bản trong JavaScript đồng bộ. Chúng đại diện cho một giá trị có thể chưa sẵn sàng但目前 sẽ được giải quyết ở một điểm nào đó trong tương lai.
Dưới đây là một ví dụ đơn giản:
let coffeePromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Cà phê của bạn đã sẵn sàng!");
}, 2000);
});
coffeePromise.then((message) => {
console.log(message);
});
Trong ví dụ này, coffeePromise
mô phỏng quá trình pha cà phê. Sau 2 giây (mô phỏng thời gian pha cà phê), nó giải quyết với một thông báo. Phương thức then
được sử dụng để xử lý promise đã giải quyết.
Async/Await: Cú pháp đường dẫn cho Promises
Cú pháp async/await
làm cho việc làm việc với promises trở nên dễ dàng hơn. Nó cho phép bạn viết mã đồng bộ mà trông và hành xử như mã đồng bộ.
async function getCoffee() {
let message = await new Promise((resolve) => {
setTimeout(() => {
resolve("Cà phê của bạn đã sẵn sàng!");
}, 2000);
});
console.log(message);
}
getCoffee();
Mã này làm cùng một điều như ví dụ trước, nhưng được viết theo cách dễ đọc và hiểu hơn.
Sử dụng vòng lặp 'for await...of'
Bây giờ chúng ta đã hiểu về các thao tác đồng bộ, hãy xem cách chúng ta có thể lặp qua chúng sử dụng vòng lặp for await...of
.
Cú pháp cơ bản
Cú pháp cơ bản của vòng lặp for await...of
trông như thế này:
async function example() {
for await (let value of asyncIterable) {
console.log(value);
}
}
Một ví dụ thực tế
Hãy tưởng tượng chúng ta có một hàm đồng bộ sinh ra các订单 cà phê:
async function* coffeeOrders() {
yield await Promise.resolve("Espresso");
yield await Promise.resolve("Latte");
yield await Promise.resolve("Cappuccino");
}
async function serveCoffee() {
for await (let coffee of coffeeOrders()) {
console.log(`Phục vụ: ${coffee}`);
}
}
serveCoffee();
Trong ví dụ này, coffeeOrders
là một hàm sinh ra đồng bộ yield các订单 cà phê. Hàm serveCoffee
sử dụng vòng lặp for await...of
để lặp qua các订单 và phục vụ chúng khi chúng sẵn sàng.
Các ứng dụng thực tế
Lặp đồng bộ đặc biệt hữu ích khi làm việc với các luồng dữ liệu hoặc khi bạn cần xử lý một lượng lớn dữ liệu từng phần.
Đọc một tệp lớn
Hãy tưởng tượng bạn cần đọc một tệp rất lớn, từng dòng:
const fs = require('fs').promises;
async function* readLines(file) {
const fileHandle = await fs.open(file, 'r');
const stream = fileHandle.createReadStream();
let buffer = '';
for await (const chunk of stream) {
buffer += chunk;
let lineEnd;
while ((lineEnd = buffer.indexOf('\n')) !== -1) {
yield buffer.slice(0, lineEnd);
buffer = buffer.slice(lineEnd + 1);
}
}
if (buffer.length > 0) {
yield buffer;
}
await fileHandle.close();
}
async function processFile() {
for await (const line of readLines('largefile.txt')) {
console.log(`Xử lý dòng: ${line}`);
}
}
processFile();
Ví dụ này minh họa cách bạn có thể sử dụng lặp đồng bộ để xử lý một tệp lớn từng dòng mà không cần tải toàn bộ tệp vào bộ nhớ một lần.
Lấy dữ liệu phân trang từ API
Một ứng dụng phổ biến khác là lấy dữ liệu phân trang từ API:
async function* fetchPages(url) {
let nextUrl = url;
while (nextUrl) {
const response = await fetch(nextUrl);
const data = await response.json();
yield data.items;
nextUrl = data.next;
}
}
async function processAllPages() {
for await (const page of fetchPages('https://api.example.com/data')) {
for (const item of page) {
console.log(`Xử lý mục: ${item.name}`);
}
}
}
processAllPages();
Ví dụ này cho thấy cách bạn có thể sử dụng lặp đồng bộ để lấy và xử lý dữ liệu phân trang từ API, xử lý từng trang khi nó được nhận.
Kết luận
Lặp đồng bộ là một công cụ mạnh mẽ trong JavaScript cho phép chúng ta làm việc với các nguồn dữ liệu đồng bộ một cách rõ ràng và trực quan. Nó đặc biệt hữu ích khi làm việc với các luồng dữ liệu hoặc khi bạn cần xử lý một lượng lớn dữ liệu từng phần.
Nhớ rằng, chìa khóa để thành thạo lặp đồng bộ là thực hành. Đừng ngại thử nghiệm với các khái niệm này trong các dự án của riêng bạn. Trước khi bạn biết, bạn sẽ xử lý các thao tác đồng bộ như một ninja JavaScript thực thụ!
Phương thức | Mô tả |
---|---|
for await...of |
Sử dụng để lặp qua các đối tượng có thể lặp đồng bộ |
async function* |
Định nghĩa một hàm sinh ra đồng bộ |
yield |
Sử dụng trong các hàm sinh ra để xác định các giá trị để lặp qua |
Promise.resolve() |
Tạo một promise đã giải quyết với giá trị cho trước |
async/await |
Cú pháp để xử lý promises một cách rõ ràng hơn |
Chúc các bạn lập trình vui vẻ, và hy vọng các thao tác đồng bộ của bạn luôn giải quyết thành công!
Credits: Image by storyset