Lớp Promise trong JavaScript

Lớp Promise trong JavaScript

Trong bài viết này, chúng tôi giải thích về lớp Promise trong JavaScript.

YouTube Video

Promise

Lớp Promise là một lớp dùng để xử lý các thao tác bất đồng bộ. Nó xử lý kết quả nếu thao tác thành công hoặc xử lý lỗi nếu thao tác thất bại. Truyền thống trước đây sử dụng các hàm callback khi bạn cần chờ một thao tác bất đồng bộ hoàn thành, nhưng Promise làm cho việc này rõ ràng hơn và mạnh mẽ hơn.

1const promise = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));
  • Đoạn mã này là một ví dụ về quá trình bất đồng bộ hiển thị "Đã xong!" sau một giây.
    • Đầu tiên, một đối tượng Promise mới được tạo ra bằng cách sử dụng new Promise. Đối số là một hàm nhận hai hàm gọi lại: resolve cho thành công và reject cho thất bại.
    • setTimeout được sử dụng để gọi resolve() sau một giây.
    • Phương thức then() của đối tượng promise đợi hoàn thành và hiển thị kết quả.

Cấu trúc cơ bản

Promise là một đối tượng mà kết quả cuối cùng sẽ dẫn đến thành công hoặc thất bại.

 1const promise = new Promise((resolve, reject) => {
 2    // Asynchronous operation
 3    // Flag indicating whether the operation was successful
 4    const success = true;
 5
 6    if (success) {
 7        resolve('Operation successful!');
 8    } else {
 9        reject('An error occurred');
10    }
11});
  • Trong trường hợp thành công, resolve() sẽ được gọi.
  • Trong trường hợp thất bại, reject() sẽ được gọi.

Đối tượng Promise có ba trạng thái.

1promise
2    .then((result) => {
3        console.log(result);
4    })
5    .catch((error) => {
6        console.error(error);
7    })
  • Đang chờ
    • Quá trình bất đồng bộ vẫn chưa hoàn thành.
  • Đã hoàn thành
    • Quá trình bất đồng bộ thành công và kết quả được trả về bởi resolve(). Kết quả được nhận bằng cách sử dụng phương thức then().
  • Đã bị từ chối
    • Quá trình bất đồng bộ thất bại và lỗi xuất hiện thông qua reject(). Lỗi được nhận bằng cách sử dụng phương thức catch().

Các phương thức then()catch()

Khi sử dụng một Promise, bạn có thể định nghĩa cần làm gì khi một thao tác bất đồng bộ hoàn thành. Để làm điều này, bạn sử dụng các phương thức then()catch().

then()

1const promise = new Promise((resolve, reject) => {
2    resolve('Operation successful!');
3});
4
5promise.then((result) => {
6    console.log(result);  // "Operation successful!"
7});
  • Phương thức then() định nghĩa một hàm sẽ được gọi khi Promise thành công.

catch()

1const promise = new Promise((resolve, reject) => {
2    reject('An error occurred');
3});
4
5promise.catch((error) => {
6    console.error(error);  // "An error occurred"
7});
  • Phương thức catch() định nghĩa một hàm sẽ được gọi khi Promise thất bại.

Phương thức finally()

 1const promise = new Promise((resolve, reject) => {
 2    resolve('Operation successful!');
 3});
 4
 5promise
 6    .then((result) => {
 7        console.log(result);
 8    })
 9    .catch((error) => {
10        console.error(error);
11    })
12    .finally(() => {
13        console.log('The operation has completed');
14    });
  • Phương thức finally() định nghĩa mã sẽ được thực thi cuối cùng, bất kể Promise thành công hay thất bại.

Chuỗi then()

then() trả về một Promise mới, vì vậy bạn có thể xâu chuỗi then() tiếp theo.

 1const promise = new Promise((resolve, reject) => {
 2    setTimeout(() => {
 3        resolve(1);
 4    }, 1000);
 5});
 6
 7promise
 8    .then(result => {
 9        console.log(result); // 1
10        return result + 1;
11    })
12    .then(result => {
13        console.log(result); // 2
14        return result + 1;
15    })
16    .then(result => {
17        console.log(result); // 3
18    })
19    .catch(error => {
20        console.error(error.message); // Something went wrong
21    });
  • Trong đoạn mã này, resolve() ban đầu truyền giá trị 1, và mỗi giá trị được trả về bởi một then sẽ được truyền sang then tiếp theo.
  • Sử dụng catch(), bạn có thể xử lý bất kỳ lỗi nào xảy ra trong chuỗi ở cùng một nơi.

Ví dụ Thực tế

Ví dụ, Promises thường được sử dụng để lấy dữ liệu từ máy chủ. Hãy xem một ví dụ sử dụng API fetch().

 1fetch('https://codesparklab.com/json/example.json')
 2    .then(response => {
 3        if (!response.ok) {
 4            throw new Error('Network error');
 5        }
 6        return response.json();
 7    })
 8    .then(data => {
 9        console.log(data);
10    })
11    .catch(error => {
12        console.error('Error:', error);
13    });
  • Trong mã này, vì fetch() trả về một Promise, nên then() được sử dụng để xử lý dữ liệu sau khi nhận được phản hồi từ máy chủ. Lỗi được xử lý bằng cách sử dụng catch().

Xử lý Nhiều Promise

Promise.all()

Để thực thi nhiều Promise cùng một lúc và tiếp tục chỉ khi tất cả thành công, hãy sử dụng Promise.all().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.resolve(2);
 3const promise3 = Promise.resolve(3);
 4
 5Promise.all([promise1, promise2, promise3])
 6    .then((results) => {
 7        console.log(results);  // [1, 2, 3]
 8    })
 9    .catch((error) => {
10        console.error('Error :', error);
11    });
  • then() chỉ được gọi khi tất cả các Promise thành công. catch() được gọi khi chỉ cần một cái thất bại.

Promise.allSettled()

Nếu bạn muốn chạy nhiều Promise đồng thời và nhận tất cả kết quả bất kể thành công hay thất bại, hãy sử dụng Promise.allSettled().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.reject("Failed");
 3const promise3 = Promise.resolve(3);
 4
 5Promise.allSettled([promise1, promise2, promise3])
 6    .then((results) => {
 7        results.forEach(result => console.log(result));
 8        // [
 9        //   { status: 'fulfilled', value: 1 },
10        //   { status: 'rejected', reason: 'Failed' },
11        //   { status: 'fulfilled', value: 3 }
12        // ]
13    });
  • then() sẽ được gọi khi tất cả các Promise đã hoàn tất (dù được thực hiện hay bị từ chối). Mỗi kết quả bao gồm một thuộc tính status ('fulfilled' hoặc 'rejected'). Ngay cả khi một số bị thất bại, điều đó cũng không ảnh hưởng đến các thao tác khác.

Promise.race()

Promise.race() trả về kết quả của Promise được giải quyết đầu tiên, dù là thành công hay thất bại.

1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5    console.log(result);  // "First"
6});
  • Như trong ví dụ này, kết quả của Promise đầu tiên hoàn tất sẽ được trả về.

Mối quan hệ giữa async/await

Sử dụng cú pháp async/await cho phép bạn viết Promises một cách trực quan hơn. Một hàm async luôn trả về một Promise, và await chờ Promise được giải quyết.

 1async function fetchData() {
 2    try {
 3        const response = await fetch('https://codesparklab.com/json/example.json');
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error('Error :', error);
 8    }
 9}
10
11fetchData();

Bằng cách sử dụng async/await theo cách này, các thao tác không đồng bộ có thể được viết như mã đồng bộ, làm cho nó dễ đọc hơn.

Tóm tắt

  • Promise là một đối tượng để xử lý thành công hoặc thất bại của các thao tác không đồng bộ.
  • Xử lý các hoạt động thành công bằng then() và lỗi bằng catch().
  • finally() định nghĩa mã sẽ được thực thi ở cuối bất kể thành công hay thất bại.
  • Bạn có thể xử lý nhiều Promise cùng nhau bằng cách sử dụng Promise.all() hoặc Promise.race().
  • async/await là cú pháp để viết Promise một cách đơn giản hơn.

Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.

YouTube Video