หลักการใช้งาน Promise and async-await in Node JS

ODENZA
2 min readMar 6, 2023

การทำงานของ node js จะทำงานแบบ asynchronous event-driven JavaScript runtime คือ จะทำงานแบบไม่เรียงลำดับ

function simulateTimeOut(text, timeout) {
setTimeout(() => {
console.log(text);
}, timeout);
}

// call functions
simulateTimeOut('A', 1000)
simulateTimeOut('B', 500)
simulateTimeOut('C', 700)

// --- results ---
B
C
A

จาก results จะเห็นได้ว่า function ไหนที่ทำงานเสร็จก่อนก็จะแสดงข้อมูลออกมาก่อน

แต่ถ้าเราอยากให้ program มันทำงานแบบเรียงตามลำดับ A B C สามารถทำได้ 3 วิธี ดังนี้

  • callback
  • Promise
  • async-await

Callback

function simulateTimeOut(text, timeout, callback) {
setTimeout(() => {
console.log(text);
callback();
}, timeout);
}

// call functions
simulateTimeOut('A', 1000, () => {
simulateTimeOut('B', 500, () => {
simulateTimeOut('C', 700, () => {
console.log('Finish callback action');
})
})
})

// --- results ---
A
B
C
Finish callback action

หลักการของ callback คือ ทำงานใน function simulateTimeOut(text, timeout, callback) เสร็จก่อนแล้วค่อยทำงานใน function callback

แต่ถ้าเรามาการเรียก callback ซ้ำๆกันหลายอันมันก็จะเกิด callback hell ทำให้ยากต่อการอ่าน code จึงมี Promise มาช่วยแก้ปัญหานี้

Promise

function simulateTimeOut(text, timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (text === 'D') return reject('D get rejected');
console.log(text);
resolve();
}, timeout);
})
}

// call functions
simulateTimeOut('A', 1000)
.then(() => {
return simulateTimeOut('B', 500)
})
.then(() => {
return simulateTimeOut('D', 700)
})
.then(() => {
return simulateTimeOut('C', 200)
})
.catch((error) => {
console.error(error)
})
.finally(() => {
console.log('Finished');
})

// --- results ---
A
B
D get rejected
Finished

.then() เป็นการทำงานต่อ เมื่อการทำงานใน simulateTimeOut เสร็จและ success นอกจากนั้นเรายังสามารถส่ง data เพื่อมาทำงานต่อใน then โดย ส่งผ่าน resolve(someData); ใน simulateTimeOut

.catch() เป็นการทำงานต่อ เมื่อการทำงานใน simulateTimeOut เสร็จแต่ error เราสามารถส่ง error data เพื่อมาทำงานต่อใน catch โดย ส่งผ่าน reject(someError); ใน simulateTimeOut

จะเห็นได้ว่า function C ไม่ทำงาน เนื่องจาก function D ได้รับ error or rejected

.finally() จะทำงานเมื่อการทำงานทั้งหมดเสร็จสิ้น

async-await

จะเห็นได้ว่า promise กับ async-await มีความคล้ายกันแต่จะต่างกันที่การเรียกใช้งาน โดยใส่ async ไปที่หน้า function และใส่ await ไปที่หน้า function ที่เรียกใช้งานเพื่อบอกให้ function นั้นรอจนกว่าจะทำงานให้เสร็จแล้วค่อยไปทำงานในบรรทัดถัดไป

ซึ่งการ handle error ก็ทำได้โดยใส่ try-catch ได้เลย

function simulateTimeOut(text, timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (text === 'D') return reject('D get rejected');
console.log(text);
resolve();
}, timeout);
})
}

// async function
async function run() {
try {
await simulateTimeOut('A', 1000)
await simulateTimeOut('B', 500)
await simulateTimeOut('C', 100)
} catch (error) {
console.error(error)
}
}

// call function
run()

// --- results ---
A
B
C

--

--