THÔNG DỤNG
OOP
ES6
ES(X)
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

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.

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.

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.

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.

 

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:

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

Cách dùng insertBefore trong javascript

Cách dùng insertBefore trong javascript

Cách dùng insertAfter trong Javascript

Cách dùng insertAfter trong Javascript

Cách dùng parentNode trong Javascript

Cách dùng parentNode trong Javascript

Cách dùng parentElement trong Javascript

Cách dùng parentElement trong Javascript

Tính tổng các phần tử trong mảng javascript

Tính tổng các phần tử trong mảng javascript

Tính tổng hai số bằng Javascript (cộng hai số)

Tính tổng hai số bằng Javascript (cộng hai số)

Cách gán giá trị cho thẻ input trong javascript

Cách gán giá trị cho thẻ input trong javascript

Để gán giá trị cho thẻ input thì ta có hai cách, thứ nhất là…

Cách kiểm tra số nguyên âm trong javascript

Cách kiểm tra số nguyên âm trong javascript

Cách kiểm tra số nguyên dương trong javascript

Cách kiểm tra số nguyên dương trong javascript

Hàm closure trong javascript

Hàm closure trong javascript

Closure là một khái niệm không phải ai cũng ..

Biểu thức chính quy RegEx trong Javascript

Biểu thức chính quy RegEx trong Javascript

Bài này chúng ta sẽ tìm hiểu đến chuỗi và cách sử dụng biểu thức…

Cách dùng Import / Export Module trong javascript

Cách dùng Import / Export Module trong javascript

Khi bạn xây dựng một ứng dụng nhỏ thì việc đặt

Cơ chế hoạt động của hoisting trong Javascript

Cơ chế hoạt động của hoisting trong Javascript

Hoisting là vấn đề liên quan đến cách khai báo biến trong Javascript. Nó liên…

Cấp độ private / protected của class trong Javascript

Cấp độ private / protected của class trong Javascript

Top