THÔNG DỤNG
OOP
ES6
ES(X)
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Hiểu rõ hơn về Promise trong Javascript - ES6

Promise là đề tài được tìm kiếm khá nhiều trong 2 năm gần đây, nhất là kể từ ngày AngularJS, NodeJS và các JS Framework khác ra đời bởi vì hầu hết chúng đều có sử dụng Promise để giải quyết xử lý bất đồng bộ (Async). Ở bài trước mình có giới thiệu sơ lược về cách sử dụng Promise rồi, tuy nhiên mình vãn đưa ra bài viết này bởi mình cần làm sáng tỏ một số vấn đề khác nữa.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Nếu bạn đang xem bài này lần đầu tiên thì mình nghĩ bạn nên quay lại đọc bài Promise trong Javascript sẽ giúp bạn dễ dàng follow hơn.

1. Ba trạng thái Pending - Fulfilled - Rejected

Ở bài trước mình có giới thiệu 3 trạng thái của Promise đó là pending, fulfilled rejected, đây là ba trạng thái mà bất kì một Promise nào cũng phải có.

Pending

Pending là trạng thái khi bạn khởi tạo một Promise nhưng chưa thiết lập kết quả cho nó, tức là chưa sử dụng resolve và reject.

Bài viết này được đăng tại [free tuts .net]

 

var promise = new Promise(function(resolve, reject){

});

console.log(promise);

 

Kết quả:

pending status promise png

Fulfilled

Fulfilled còn được gọi là resolved, đây là trạng thái của Promise đã thành công, trạng thái này xảy ra khi bạn sử dụng resolve.

 

var promise = new Promise(function(resolve, reject){
    resolve();
});

console.log(promise);

 

Kết quả:

resolve status promise png

Rejected

Rejected là trạng thái thao tác thất bại, trạng thái này xảy ra khi bạn sử dụng reject. Khi bạn sử dụng reject thì bắt buộc phải khai báo hành động xử lý cho nó (tức sử dụng then hoặc catch).

 

var promise = new Promise(function(resolve, reject){
    reject();
});

promise.catch(function(){
    // Something
});

console.log(promise);

 

Kết quả:

reject status promise png

2. Thenable liên tiếp

Phương thức then() có nhiệm vụ tiếp nhận kết quả trả về của promise và nó cũng return về một promise nên bạn có thể dùng nhiều lần liên tiếp với nhau.

 

var promise = new Promise(function(resolve, reject){
    resolve();
});

promise.then(function(){
            console.log(1);
        })
        .then(function(){
            console.log(2);
        })
        .then(function(){
            console.log(3);
        });

 

Kết quả:

thenable lien tiep trong promise png

Việc đặt thứ tự các phương thức rất quan trọng nhé các bạn. Nếu hành động của promise trả về là một Reject thì sẽ có hai trường hợp xảy ra như sau:

Trường hợp 1: Nếu trong phương thức then() nào đó có sử dụng callback function Reject thì các phương thức then() ở phía sau sẽ là một Fulfilled, nghĩa là nó sẽ chạy ở callback function Resolve.

 

var promise = new Promise(function(resolve, reject){
    reject();
});

promise.then(function(){
            console.log(1);
        })
        .then(function(){
            console.log(2);
        }, function(){
            console.log('Error!')
        })
        .then(function(){
            console.log(3);
        });

 

Kết quả:

thenable lien tiep trong promise 1 png

Nếu chiếu theo quy luật thì ở biến promise mình đã sử dụng Reject nên suy ra ở then() tham số callback thứ hai sẽ hoạt động. Điều này hoàn toàn đúng với phương thức then() thứ hai, vì vậy nó in ra chư Error!. Tuy nhiên nhảy qua phương thức then() thứ tư thì nó lại chạy phần callback Resolve nên in ra số 3.

Trường hợp 2: Bạn sử dụng catch để bắt lỗi, lúc này chỉ có phương thức catch() là hoạt động.

 

var promise = new Promise(function(resolve, reject){
    reject();
});

promise.then(function(){
            console.log(1);
        })
        .then(function(){
            console.log(2);
        })
        .then(function(){
            console.log(3);
        })
        .catch(function(){
            console.log('Error!')
        });

 

Kết quả:

thenable lien tiep trong promise 2 png

Ôi tới đây thì mình đã mắc một sai lầm nghiêm trọng. Thật ra thì hai trường hợp kia chỉ là lý luận theo hướng mắt thấy tai nghe nên nó không đúng đâu các bạn nhé, vấn đề nằm ở câu chốt dưới này :)

Khi sử dụng thenable liên tiếp thì kết quả return của phương thức then() hiện tại sẽ quyết định trạng thái của phương thức  then() tiếp theo. Ví dụ then() phía trên return về một Promise Rejected thì then() phía dưới sẽ nhận một trang thái Rejected.

Mình sẽ lấy một ví dụ như sau:

 

asyncPromise1()
        .then(function () {
            return asyncPromise2();
        })
        .then(function () {
            return asyncPromise3();
        })
        .catch(function (err) {
            return asyncRecovery1();
        })
        .then(function () {
                return asyncPromise4();
            }, function (err) {
                return asyncRecovery2();
            }
        )
        .catch(function (err) {
            console.log("Đừng lo lắng gì cả :)");
        })
        .then(function () {
            console.log("Mọi thứ đã xong!");
        });

 

Kết quả của đoạn code đó phụ thuộc vào các Async mà nó return về. Và sau đây là bảng mô tả các trường hợp xảy ra.

thenable lien tiep trong promise 3 png

Trong hình này đường màu xanh mô tả cho Async Promise return về một Fulfilled và màu tím mô tả cho Asycn Promise return về một Rejected.

Lấy một ví dụ chạy thực luôn cho các bạn xem nhé.

 

var promise = new Promise(function(resolve, reject){
    resolve();
});

promise
    .then(function(){
        return new Promise(function(resolve, reject){
            reject();
        });
    })
    .then(function(){
        console.log('Success!');
    })
    .catch(function(){
        console.log('Error!');
    });

 

Kết quả:

thenable lien tiep trong promise 4 png

then() thứ nhất return về một Reject Promise nên then() thứ hai không chạy, và trạng thái bây giờ là Rejected nên catche sẽ được chạy => in ra chữ Error!.

Vậy là hết rồi đó !

3. Lời kết

Rõ ràng Promise trong Javascript nói chung và trong ES6 nói riêng rất phức tạp phải không các bạn, hôm nay mình mất đúng một ngày mới biên soạn xong hai bài này đấy :)

Việc hiểu nguyên tắc hoạt động của Promise rất quan trọng, nếu  không bạn sẽ rất dễ mắc phải các lỗi về Callback Hell  đấy. Cuối cùng chúc bạn học tốt và luôn ủng hộ freetuts.net nhé.

Cùng chuyên mục:

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

4 cách tránh memory leaks trong JavaScript

4 cách tránh memory leaks trong JavaScript

Capturing và bubbling Event trong Javascript

Capturing và bubbling Event trong Javascript

Phân biệt prototype và __proto__ trong JavaScript

Phân biệt prototype và __proto__ trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Cách khắc phục lỗi

Cách khắc phục lỗi "hoisting" trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Cách sử dụng Async functions trong JavaScript

Cách sử dụng Async functions trong JavaScript

Hàm String isspace() trong Python

Hàm String isspace() trong Python

Cách tạo số ngẫu nhiên trong Javascript

Cách tạo số ngẫu nhiên trong Javascript

Hướng dẫn cách tạo một số ngẫu nhiên ...

Cách gộp hai object javascript lại với nhau

Cách gộp hai object javascript lại với nhau

Cách lấy chiều dài của object trong Javascript

Cách lấy chiều dài của object trong Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Cách dùng nextSibling trong javascript

Cách dùng nextSibling trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng innerHTML trong Javascript

Cách dùng innerHTML trong Javascript

Top