Tìm hiểu về Javascript Promise
Javascript
200
White

Hoàng Nguyễn viết ngày 27/01/2016

Trong bài AngularJS cho người mới: Dependencies và Services cũng như một số bài viết khác tôi đã có đề cập đến khái niệm promise trong Javascript, hôm nay tôi sẽ giới thiệu rõ hơn về promise cũng như ý nghĩa là tác dụng của nó. Nào cùng bắt đầu nhé.

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.

Tại sao lại sử dụng Promise?

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.

Promise States

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.
  • Fullfilled – 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 (fullfilled). 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 (fullfilled) 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.

Sử dụng Promise

Đ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 “hello world” được viết dưới dạng thông thường (synchronous).

var greeting = sayHello();
console.log(greeting); // 'hello world’

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); // 'hello world’
});

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); // 'hello world’
}, function (error) {
    console.error('something went wrong: ', error);   // 'something went wrong: blabla’
});

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.

Chuyển đổi giá trị trong tương lai

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); // 'hello world!’
});

Chuỗi các tác vụ bất đồng bộ

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); // 'hello world!’
});

Thì chúng ta có thể viết một cách đơn giản hơn như sau.

var greetingPromise = sayHello();
greetingPromise
    .then(addExclamation)
    .then(function (greeting) {
        console.log(greeting); // 'hello world!’
    });

Xử lý lỗi

Đ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); // 'hello world!’
} catch(error) {
    console.error('something went wrong: ', error);   // 'something went wrong: blabla’
}

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); // 'hello world!’
    }, function(error) {
        console.error('something went wrong: ', error); // 'something went wrong: blabla’
    });

Hy vọng qua những điều hướng dẫn cơ bản đã nêu ra, các bạn đã có thể hiểu được promise trong javascipt là gì, làm thế nào để sử dụng cũng như áp dụng promise vào các trường hợp thực tế.

Chào tạm biệt và hẹn gặp lại.

Bài gốc: https://codeaholicguy.wordpress.com/2016/01/26/tim-hieu-ve-javascript-promise/

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Hoàng Nguyễn

35 bài viết.
364 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
76 34
Nhu cầu về Javascript developer hiện nay trong thị trường IT là rất lớn. Nếu bạn có kiến thức ở mảng này thì cơ hội nghề nghiệp cũng như thu nhập c...
Hoàng Nguyễn viết hơn 1 năm trước
76 34
White
49 19
Microservices hiện đang nhận được rất nhiều sự chú ý: các bài viết, các blog, các cuộc thảo luận trên phương tiện truyền thông, trên mạng xã hội, v...
Hoàng Nguyễn viết hơn 2 năm trước
49 19
White
29 2
Chuyện tối ưu code, (Link) là công việc hàng ngày của mỗi lập trình viên, điều đó ai cũng biết. Nhưng liệu code tối ưu có phải là code đẹp, và ngượ...
Hoàng Nguyễn viết 3 tháng trước
29 2
Bài viết liên quan
White
39 7
Tăng sức mạnh cho javascript với lodash Lần này mình sẽ giới thiệu 1 thư viện javascript vô cùng bá đạo có tên là "lodash]1]", có thể nói nó là LI...
Huy Hoàng Phạm viết hơn 2 năm trước
39 7
White
21 8
Lâu không post gì muốn viết một bài dài dài về js cơ mà đau đầu quá viết mãi không xong, thôi post bài ngắn vậy :smiley: Lấy screen size ở đây tôi...
Hoàng Duy viết hơn 2 năm trước
21 8
White
3 0
Có bao giờ bạn thắc mắc, chuyện gì thực sự diễn ra khi chúng ta gõ một địa chỉ trang web (ví dụ: (Link)) lên trình duyệt và nhấn Enter? Đầu tiên, t...
Lam Pham viết 1 tháng trước
3 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
35 bài viết.
364 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!