+8

Javascript Promise - Lời hứa cho tình yêu

Promise được đưa vào Javascript từ ES6, đây có thể coi là một kỹ thuật nâng cao giúp xử lý vấn đề bất đồng bộ hiệu quả hơn. Trước đây kết quả của một tác vụ đồng bộ và bất đồng bộ sẽ trả về một kiểu dữ liệu nào đó hoặc thực hiện một Callback Function. Với trường hợp thực hiện Callback Function thì sẽ dễ xảy ra lỗi Callback Hell, nghĩa là gọi callback quá nhiều và lồng nhau nên dẫn đến không kiểm soát được chương trình hoặc bộ nhớ không đủ để hoạt động.Và trong bài viết này mình muốn giới thiệu thêm cho các bạn về Promise và những lời hứa tình yêu ngọt ngào mà nó mang lại từ ES6 đến bây giờ. Để đảm bảo là bài viết không quá dài dòng và nặng qúa nhiều mùi lý thuyết, mình xin được phép mặc định rằng tất cả người đọc đều đã biết về xử lý đồng bộ/bất đồng bộ. Hy vọng rằng sẽ có thời gian để viết 1 bài riêng về nó trong thời gian gần nhất 😄

1. Promise là gì?

Promise được sinh ra để thể hiện cho kết quả sau cùng của một tác vụ bất đồng bộ (asynchronous operation). Nó là một placeholder mà trong nó kết quả của việc thực thi tác vụ bất đồng bộ đó dù thành công hay thất bại sẽ được hiện thực.

2. Promise thì có gì vui?

Nếu so sánh với các phướng thức callback-based truyền thống thì promise cung cấp một biện pháp thay thế đơn giản hơn trong việc thực thi, biên soạn và quản lý các tác vụ bất đồng bộ. Hơn cả, promise cho phép chúng ta handle các lỗi xảy ra khi thực thi tác vụ bất đồng bằng các sử dụng các phương thức tiếp cận tương tự với sử dụng try/catch trong các tác vụ đồng bộ (synchronous) thông thường.

3. Các trạng thái của Promise

Promise có thể ở một trong ba trạng thái.

  • Pending – trang thái khởi tạo, lúc này kết quả của promise vẫn chưa được xác định, bởi vì tác vụ bất đồng bộ vẫn chưa hoàn thành.
  • Fulfilled – trạng thái hoàn thành, tác vụ bất đồng bộ đã hoàn thành, và promise đã có giá trị.
  • Rejected – trạng thái bị từ chối, tác vụ bất đồng bộ thực thi thất bại, và promise sẽ không bao giờ được hoàn thành (fulfilled). Trong trạng thái bị từ chối (rejected) một promise sẽ chứa một lý do (reason) để chỉ ra tại sao việc thực thi thất bại.

Khi một promise đang ở trạng thái khởi tạo (pending), nó có thể chuyển sang trạng thái hoàn thành (fulfilled) hoặc bị từ chối (rejected). Một khi promise được hoàn thành hoặc bị từ chối, thì đó sẽ là giá trị cuối cùng, promise đó sẽ không thể chuyển thành trạng thái khác được nữa, và vì thế giá trị của nó hoặc lý do thực hiện thất bại sẽ không thay đổi

4. Dùng Promise sao cho đẹp trai?

Điểm quan trọng nhất của một API cho promise chính là phương thức then(), đây chính là cái mà các callback đăng kí vào để nhận giá trị trả về hay lý do promise không thể hoàn thành. Dưới đây là một đoạn code được viết dưới dạng thông thường (synchronous).

var greeting = sayHello();
console.log(greeting); // 'chao anh dep trai’

Tuy nhiên, nếu phương thức sayHello là một phương thức bất đồng bộ, và cần lấy dữ liệu từ một web service nào đó trả về, chúng ta có thể chuyển nó thành promise như sau.

var greetingPromise = sayHello();
greetingPromise.then(function (greeting) {
    console.log(greeting); // 'chao anh dep trai’
});

Message vẫn được in ra console, nhưng giờ đây, những block code khác có thể tiếp tục chạy khi lời chào đang được fetch.

Như tôi đã nói ở trên, một promise có thể đại diện cho một thất bại. Nếu như network có vấn đề và lời chào không thể được fetch từ web service, chúng ta có thể đăng kí một callback để giải quyết các lỗi bằng cách sử dụng tham số thứ hai của phương thức then như sau.

var greetingPromise = sayHello();
greetingPromise.then(function (greeting) {
    console.log(greeting); // 'chao anh dep trai'
}, function (error) {
    console.error('something went wrong: ', error);   // 'something went wrong: co dua khac dep trai hon anh’
});

Nếu sayHello thành công, lời chào sẽ được in ra console, nhưng nếu nó thất bại, thì lý do thất bại sẽ được in ra console bằng console.error.

5. "Cỗ máy thời gian" promise

Một khía cạnh mạnh mẽ của promise là cho phép chúng ta có thể chuyển đổi giá trị trả về trong tương lai bằng việc trả về một giá trị mới trong callback và truyền nó vào trong phương thức then. Ví dụ.

var greetingPromise = sayHello();
greetingPromise.then(function (greeting) {
    return greeting + '!';
}).then(function (greeting) {
    console.log(greeting); // 'chao anh dep trai!’
});

6. Hệ thống các tác vụ bất đồng bộ chạy thế nào?

Một function được truyền vào then có thể trả về giá trị là một promise khác. Điều này cho phép các tác vụ bất động bộ tạo thành một chuối mắt xích với nhau, cũng vì thế mà có thể dảm bảo rằng chúng xảy ra theo thứ tự đúng đắn. Lấy ví dụ, nếu hàm thêm dấu “!” (addExclamation) là một tác vụ bất đồng bộ và trả về một promise để các hàm gọi lời chào tiếp theo được thực hiện như sau.

var greetingPromise = sayHello();
greetingPromise.then(function (greeting) {
    return addExclamation(greeting); // addExclamation returns a promise
}).then(function (greeting) {
    console.log(greeting); // 'chao anh dep trai!’
});

7. Lỗi một phát thì làm sao?

Điều gì xảy ra nếu có lỗi trong khi thực hiện tác vụ bất đồng bộ? ví dụ như hàm sayHello, hoặc addExclamation bị fail?

Trong code synchronous, chúng ta sử dụng try/catch and dựa vào exception để handle lỗi. Dưới đây sẽ là các code synchronous thông thường, dùng try/catch để xử lý lỗi. Nếu có lỗi xảy ra, thì catch block sẽ được thực thi, in lỗi ra console.

var greeting;
try {
    greeting = sayHello();
    greeting = addExclamation(greeting);
    console.log(greeting); // 'chao anh dep trai!’
} catch(error) {
    console.error('something went wrong: ', error);   // 'something went wrong:  co dua khac dep trai hon anh’
}

Khi thực hiện với các tác vụ bất đồng bộ, try/catch block ko thể sử dụng được nữa. Tuy nhiên, promise cho phép chúng ta handle lỗi của các tác vụ bất đồng bộ bằng cách đơn giản hơn, không chỉ cho phép chúng ta viết code asynchronous tương tự với style code synchronous, mà còn kiểm soát được flow và handle lỗi tương tự như synchronous code.

Dưới đây và phiên bản asynchronous dùng để handle lỗi.

var greetingPromise = sayHello();
greetingPromise
    .then(addExclamation)
    .then(function (greeting) {
        console.log(greeting); // 'chao anh dep trai!’
    }, function(error) {
        console.error('something went wrong: ', error); // 'something went wrong: co dua khac dep trai hon anh’
    });

Chương trình lượm lặt tổng hợp phân tích báo cáo đánh giá về promise đến đây là hết, các bạn có thể tìm hiểu kỹ hơn ở những nguồn bên dưới 😄 Nguồn: https://spring.io/understanding/javascript-promises https://codeaholicguy.com/2016/01/26/tim-hieu-ve-javascript-promise/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí