Promise Javascript - Nhậu bình dân và ăn gà rán KFC

Nội dung bài viết

Promise Javascript trong bài viết này sẽ nói đến một tình huống rất gần gũi với chúng ta. Thông qua hai việc đó là đi nhậu và dẫn người yêu đi ăn gà KFC là bạn có thể hiểu về lập trình đồng bộ trong Javascript. 


Người người nhà nhà đều biết rằng Promise được biết đến khi ES6 (ECMAScript 2015) cho ra đời. Đến bây giờ đã là ES12 (ECMAScript 2021) nhưng vẫn còn một số bạn vẫn có câu hỏi rằng? Anh ơi em thấy Promise ít sử dụng nên không phổ biến. Vậy khi học có nên tập trung vào hay không? Câu trả lời sẽ có trong ít phút nữa. Để có cái nhìn gần gửi hơn, một đề xuất được đưa ra cho bài viết này, nhằm giúp những bạn mới học nắm bắt nhanh, mục tiêu của bài viết này là vậy. 


Đây là một bài viết nêu lên quan điểm của cá nhân, không đánh vào số đông, chỉ cho những bạn mới học mà thôi. Nếu bạn có một ý kiến nào, xin vui lòng inbox vào fanpage tips Javascript. Ở đó, chúng tôi sẽ tiếp thu một cách nghiêm túc nhất. Còn nếu như bạn có một số câu hỏi thì vui lòng truy cập vào nhóm Javascript Việt Nam để bày tỏ.


Promise Javascript - Nhìn vào cuộc sống thực tế


Cuộc sống thực tế, nếu sống một cách logic thì sẽ lập trình logic và ngược lại... 

Câu chuyện 1: Anh Tèo dẫn người yêu đi ăn gà KFC. Vào quán, anh quan sát và chọn lựa một chỗ ngồi thật đẹp và ngoài ra ngằm được mục tiêu khác nữa kakak. Bây giờ chúng ta hay quan sát những yêu cầu thực hiện của Cửa hàng KFC như thế nào? 


Đầu tiên, Anh Tèo chọn món ăn, sau đó đi vào quán thanh toán tiền, khi thanh toán xong có một phiếu và một số để đánh dấu. Tiếp đó là ngồi chờ để có đồ ăn. Trong lúc đang chờ đố ăn thì, con người yêu nó lại thích thêm món nữa, thế là cắn răng chịu đựng Anh Tèo lại lặp lại qúa trình đó, nhưng không may là rất đông, nên phải xếp hàng chờ thanh toán mới có đồ ăn. Đến đây thôi, Anh Tèo lộn cái bàn. Bực bội... 


15 phút sau có đồ ăn. Trong lúc ăn, Anh Tèo lại gọi thêm món, mà nghĩ tới cảnh phải xếp hàng, bon chen, thanh toán các kiểu nên thôi. Mang cục tức ra về, hết vui vẻ.


Lập trình bất đồng bộ trong javascript


Thì câu chuyện trên sẽ được mô tả với promise trong Javascript như sau:

function sleep(second, param) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(param);
        }, second);
    })
}

async function gaKFC() {
    let result1 = await sleep(2000, 'Step1 - xếp hàng');
    let result2 = await sleep(1000, 'Step2 - Thanh Toán khi đã xong ' + result1);
    let result3 = await sleep(500, 'Step3 - Chờ và ăn khi đã xong ' + result2);
    console.log(`
        ${result3}
        ${result2}
        ${result1}
    `);
}

gaKFC();

/*
 	Step3 - Chờ và ăn khi đã xong Step2 - Thanh Toán khi đã xong Step1 - xếp hàng
 	Step2 - Thanh Toán khi đã xong Step1 - xếp hàng
 	Step1 - xếp hàng
/*

Ưu điểm của cách làm này nhìn rất văn minh và lịch sự. Giải quyết rõ ràng từng khâu, hệ thống giải quyết từng bước một. Có một câu nổi tiếng đó là "Nhìn nó đồng bộ, nhưng thật ra là bất động bộ". 


Câu chuyện 2: 

Sau khi đưa người yêu đi ăn gà KFC về, bực bội vì có qúa nhiều công đoạn phải phụ thuộc cho nên Anh Tèo hẹn anh em ra quán nhậu. Khi ra quán nhậu, Anh Tèo được các em phục vụ tận răng, trong khi gọi món thì được "lên bia em ơi". Vừa nhâm nhi ly bia vừa gọi món. Nó sướng khó tả... Sau khi có món, thì vừa nhậu vừa gọi món thứ hai, thứ ba... Đến khi say sưa, Anh Tèo vừa làm nốt chai cuối cùng để tính tiền. Khi tình tiền Anh Tèo và những người bạn làm nốt những giọt cuối cùng. Quá sướng... Và đặc biệt khi tính tiền, bạn anh Tèo đi vệ sinh hết :D 


Promise all javascript


Thì câu chuyện trên sẽ được mô tả được sự giúp đỡ của Promise all sau. Nên nhớ chúng tôi có rất nhiều bài viết nói về "Promise all là gì?" Ở đây không nói thêm.

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('request done! ' + Math.random());
        }, second);
    })
}

async function nhauBinhDan() {
    await sleep(1000); // gọi món
    await sleep(1000); // nhậu 
    await sleep(1000); // Tính tiền
    console.log('Nhậu anh em ơi....');
}

nhauBinhDan();

Ở trên là tình huống sai, không đúng với mô tả tình huống trên, và đây cũng là một trong những sai lầm nhất khi lập trình async/await. Vì sao sai, thì các bạn nên đọc lại 19 bài viết về async/await. Cách này mới thực sự là đúng.

async function correctDemo() {
    let p1 = sleep(1000); // gọi món
    let p2 = sleep(1000); // nhậu
    let p3 = sleep(1000); // Tính tiền
    await Promise.all([p1, p2, p3]);
    console.log('Nhậu anh em ơi....');
}

Promise error handling


Ở phần này, tôi sẽ nói thêm về xử lý lỗi promise all. Trở lại với bài viết khi sử dụng promise.all() thì bạn chú ý những điều sau đây: Giả sử chúng ta có một code sau đây:

Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])
.then(res => console.log(res),err=>console.log(err))
// [1, 2, 3]

////// Example 2
Promise.all([Promise.reject(1), Promise.resolve(2), Promise.resolve(3)])
.then(res => console.log(res),err=>console.log(err))
// 1

Example 2 cho ta thấy khi một trong những promise return reject thì nó kết thúc và nhanh chóng đưa ra kết quả, vậy làm sao chúng ta "Error handling with promise". Chúng ta có thể viết lại như sau:

Promise.all([
    Promise.reject(1).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err })),
    Promise.resolve(2).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err })),
    Promise.resolve(3).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err }))
]).then(res => console.log(res), err => console.log(err))

/*
[{
  err: 1,
  status: "not ok"
}, {
  res: 2,
  status: "ok"
}, {
  res: 3,
  status: "ok"
}]
*/

Nhưng nếu muốn thanh lịch hơn, có thể cách này giúp bạn có một cái nhìn rõ ràng hơn.

// Một hàm xử lý chung 
function handlePromise(promiseList) {
    return promiseList.map(promise =>
      promise.then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err }))
    )
 }

Promise.all(handlePromise([Promise.reject(1),Promise.resolve(2),Promise.resolve(3)]))
.then(res => console.log(res),err=>console.log(err))

/*
[{
  err: 1,
  status: "not ok"
}, {
  res: 2,
  status: "ok"
}, {
  res: 3,
  status: "ok"
}]
*/

Nói vậy thôi, nếu bạn không hiểu thì đừng nản, có nhiều bài viết về "Lập trình bất đồng bộ trong javascript" mà các bạn có thể hiểu nhiều hơn. Không ai tài giỏi gì hết, chẳng qua họ đi nhiều thành đường mà thôi. Thanks!

Có thể bạn đã bị missing