+2

Callback và Promise trong javascript(18+ version)

Callback

Giả sử bạn là sinh viên nghèo nhưng ham học. Vì học nhiều nên đầu óc căng thẳng, mệt mỏi, bạn đã nảy ra ý định dẫn gấu đi nhà nghỉ cho đỡ mệt. Chuẩn bị gọi cho gấu thì bạn nhận ra trong ví còn có 100k. Thế này méo ổn, dạo này trên mạng ra rả chuyện của mấy thằng mang 100k đi chơi(với) gấu, đa số là bị chửi cho sấp mặt lá.

var tiền_của_bạn = 100;

Bạn đành gọi điện về quê xin tiền mẹ để học tiếng Tung Của, 2 anh em sắp sum họp 1 nhà, bảo bà gửi lên gấp. Bà già bạn, thấy con mình ham học như thế nên cũng chẳng tiếc tiền đầu tư. Nhưng trước khi rút hầu bao, bà cũng ca cho một bài dài như bài "Nhật ký của mẹ" mà Hiền Thục hay hát, chứ ko bao giờ bạn xin cái bà cho ngay.

function xin_mẹ_tiền_đóng_học(số_tiền_muốn_xin) {
    setTimeout(function() {
        tiền_của_bạn += số_tiền_muốn_xin * 0.5;
    }, 1000)
}

Bạn đã quen với việc bà già chỉ cho 1 nửa số tiền bạn xin nên ko có gì lạ ở đây cả. Bạn dự định sẽ cố đợi cho hết cái Timeout rồi mới rủ gấu đi. Nhưng gấu bạn cũng là sinh viên, cũng học chăm nên mệt, cần đi nghỉ. Vậy là nó chủ động gọi cho bạn. Bạn từ chối quanh co nhưng cuối cùng vẫn đi vì chả lẽ nói "Anh đợi tiền bu anh gửi lên đã", như thế nghe nó hèn hèn làm sao ấy.

function xin_mẹ_tiền_đóng_học(số_tiền_muốn_xin) {
    setTimeout(function() {
        tiền_của_bạn += số_tiền_muốn_xin * 0.5;
    }, 1000)
}

function dẫn_gái_đi_nghỉ_trong_nhà() {
    if(tiền_của_bạn > 100){
        console.log("Nhà nghỉ gì mà càng nghỉ càng mệt! :D");
    }else{
        console.log("Bị gái chửi cho sấp mặt lá vì đi chơi mang có 100k");
    }
}
xin_mẹ_tiền_đóng_học(100);
dẫn_gái_đi_nghỉ_trong_nhà();

Kết quả

Giá mà bạn chịu khó đợi vài ngày khi bà già gửi tiền lên thì mọi chuyện đã khác.

...
xin_mẹ_tiền_đóng_học(100);
setTimeout(function(){
    dẫn_gái_đi_nghỉ_trong_nhà();
}, 2000);

Ở trên mình để timeout là cho việc xin tiền 1000, sau bạn đợi 2000, vậy là chắc chắn bạn nhận được tiền. Còn trong thực tế bạn ko biết khi nào nhận được tiền cả.

function xin_mẹ_tiền_đóng_học(số_tiền_muốn_xin, timeout) {
    setTimeout(function() {
        tiền_của_bạn += số_tiền_muốn_xin * 0.5;
    }, timeout)
}

Cái timeout do bà già quyết định nên bạn chỉ có thể kiểm tra tk liên tục xem có tiền chưa để quyết định đi thôi. Như vậy rất bất tiện. Giải pháp ở đây là bạn xui đứa em gái bạn theo dõi bà già, khi nào bà gửi tiền thì nó báo lại cho bạn biết để bạn đi tìm nhà, nghỉ cho đỡ mệt.

function xin_mẹ_tiền_đóng_học(số_tiền_muốn_xin, em_gái_báo_tin) {
  setTimeout(function() {
    tiền_của_bạn += số_tiền_muốn_xin*0.5;
    em_gái_báo_tin();
  }, 1000)
}
xin_mẹ_tiền_đóng_học(100, function() {
  dẫn_gái_đi_nghỉ_trong_nhà();
});

Cái trên người ta gọi là callback.

Promise

Mẹ bạn là người thích hứa, từ hồi bé bạn đã biết, cứ học giỏi vào, rồi mẹ cho cái điện thoại, cái laptop. Nhưng có khi thì bà giữ lời hứa, có khi thì không, tùy xem hôm đó bà trúng lô hay trượt. Dù vậy thì bạn cũng thích bà hứa cái này cái kia, hơn là cứ phải nhờ con em gái làm gián điệp. Lý do:

  • Đến khi con em gái bạn không còn đáng tin nữa(khi nó có gấu), thì bạn cần thuê 1 gián điệp nữa để theo dõi nó. Rồi gián điệp mới cũng ko đáng tin, bạn lại thuê 1 gián điệp nữa để canh chừng gián điệp này... Cứ như vậy bạn rất tốn tiền thuê gián điệp và còn khó kiểm soát.
  • Trúng lô hay trượt lô thì sau 18h30 là bạn biết kết quả, ko phải ngóng nhiều. 😄
var tiền_của_bạn = 100;

function xin_mẹ_tiền_đóng_học(số_tiền_muốn_xin) {
    var promise = new Promise(function(resolve, reject){
        var chỉ_số_vui_vẻ = Math.floor(Math.random() * 10);
        if (chỉ_số_vui_vẻ > 5) {
          tiền_của_bạn += số_tiền_muốn_xin*0.5;
          resolve();
        } else {
          reject('Vừa trượt con lô, ko thì mẹ cho mày gấp đôi rồi, đợi lần sau con nhé!');
        }
    });
    return promise
}

function dẫn_gái_đi_nghỉ_trong_nhà() {
    console.log("Nhà nghỉ gì mà càng nghỉ càng mệt! :D");
}

xin_mẹ_tiền_đóng_học()
.then(
    function() {
        dẫn_gái_đi_nghỉ_trong_nhà();
    },
    function(msg) {
       console.log(msg);
    }
);

Bạn chạy code vài lần để nó random kết quả nhé.

Kết luận

Trong jsvascript, bạn cần thận trọng với các tác vụ bất đồng bộ. Không phải cái gì viết trước thì nó chạy trước. Do đó, khi cần xử lý kết quả của các tác vụ tốn thời gian(như call API, load image, read file...) thì bạn cần kiểm soát được trạng thái của các tác vụ đó, nếu không kết quả của chương trình có thể ko như mong muốn.

Thanks for reading!!!


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í