ลำดับการทำงานใน JavaScript จะแบบออกเป็น 2 ลักาณะ
1.Non-Blockin หรือ อะซิงโครนัส Asynchronous
คือการทำงานแบบไม่พร้อมกัน หรือไม่ต่อเนื่องกัน โดยงานบางส่วนที่ต้องใช้เวลา หรือมีการหน่วงเวลา งานส่วนนี้จะถูกทำงานในเบื้องหลัง ส่วนงานอื่นที่ไม่ต้องรอเวลา หรือไม่ได้ถูกหน่วงเวลาไว้ จะสามารถทำงานล่วงหน้าไปก่อนได้เลย
ตัวอย่างคำสั่ง
- setTimeout
- setInterval
- Promise
2.Blocking หรือ Synchronous
คือเป็นการทำงานที่ทำตามลำดับ มีการหยุดรอให้ส่วนแรกดำเนินการเสร็จก่อน จึงจะทำงานในลำดับต่อไป
ตัวอย่างคำสั่ง
- comfirm
ตัวอย่าง ปัญหาที่เจอ ของการทำงานแบบ asynchronous
console.log("เริ่มต้นโหลด") console.log("กำลังทำงาน") console.log("จบการทำงาน")
เริ่มต้นโหลด กำลังทำงาน จบการทำงาน
เมื่อมีการ setTimeout ทำให้ลำดับการทำงาน ไม่ถูกต้อง
console.log("เริ่มต้นโหลด") setTimeout(()=>{ console.log("กำลังทำงาน") },3000) console.log("จบการทำงาน")
เริ่มต้นโหลด จบการทำงาน กำลังทำงาน
Callback function
แบบปกติ ที่ยังไม่ได้ setTimeout
function calculate(x, y) { return x + y } function display(result) { console.log(`ผลบวก ${result}`); } const sum = calculate(100,50) display (sum)
ผลบวก 150
แบบ setTimeout ทำให้ได้ผลลัพธ์ที่ไม่ถูกต้อง display() ทำงานก่อน โดยไม่ calculate() ที่มีการ setTimeout ไว้
function calculate(x, y) { setTimeout(() => { console.log("กำลังคำนวณ......"); return x + y }, 3000) } function display(result) { console.log(`ผลบวก ${result}`); } const sum = calculate(100, 50) display(sum)
ผลบวก undefined กำลังคำนวณ......
การแก้ปัญหาด้วย callback function
function calculate(x, y,callback) { console.log("กำลังคำนวณ......"); setTimeout(() => { const sum = x + y callback(sum) }, 3000) } function display(result) { console.log(`ผลบวก ${result}`); } const sum = calculate(100, 50,display)
กำลังคำนวณ...... ผลบวก 150
เขียนแบบลดรูปลงไปอีกแบบ
function calculate(x, y,callback) { console.log("กำลังคำนวณ......"); setTimeout(() => { const sum = x + y callback(sum) }, 3000) } calculate(100, 50,function(result){ console.log(`ผลบวก ${result}`); })
และอีกแบบ
function calculate(x, y,callback) { console.log("กำลังคำนวณ......"); setTimeout(() => { const sum = x + y callback(sum) }, 3000) } calculate(100, 50,(result)=>{ console.log(`ผลบวก ${result}`); })
การเขียนแบบปกติ
const url1 = "kong.dev/file1.json" function dowloading(url) { console.log(`กำลังดาวโหลด ${url}`) } function complete() { console.log("ดาวโหลดเรียบร้อย!"); } dowloading(url1) complete()
กำลังดาวโหลด kong.dev/file1.json ดาวโหลดเรียบร้อย!
การทำงานเมื่อมีการ setTimeout ผลที่ได้คืองานไม่ถูกต้องตามลำดับ
const url1 = "kong.dev/file1.json" function dowloading(url) { setTimeout(() => { console.log(`กำลังดาวโหลด ${url}`) , 3000 }) } function complete() { console.log("ดาวโหลดเรียบร้อย!"); } dowloading(url1) complete()
ดาวโหลดเรียบร้อย! กำลังดาวโหลด kong.dev/file1.json
แก้ไขด้วยการใช้ callback
const url1 = "kong.dev/file1.json" function dowloading(url,callback) { console.log(`กำลังดาวโหลด ${url}`) setTimeout(() => { callback() }, 3000) } dowloading(url1,()=>{ console.log("ดาวโหลดเรียบร้อย!"); })
กำลังดาวโหลด kong.dev/file1.json ดาวโหลดเรียบร้อย!
และอีกแบบ กรณีต้องการส่งต่อค่าเข้าไปใน callback ด้วย
const url1 = "kong.dev/file1.json" function dowloading(url, callback) { console.log(`กำลังดาวโหลด ${url}`) setTimeout(() => { callback(url) }, 3000) } function complete(result) { console.log(`ดาวโหลด ${result} เรียบร้อย!`) } dowloading(url1, complete)
กำลังดาวโหลด kong.dev/file1.json ดาวโหลด kong.dev/file1.json เรียบร้อย!
หรือเขียนอีกแบบ ลดรูปลงไป
const url1 = "kong.dev/file1.json" function dowloading(url, callback) { console.log(`กำลังดาวโหลด ${url}`) setTimeout(() => { callback(url) }, 3000) } dowloading(url1, (result)=>{ console.log(`ดาวโหลด ${result} เรียบร้อย!`) })
กำลังดาวโหลด kong.dev/file1.json ดาวโหลด kong.dev/file1.json เรียบร้อย!
ตัวอย่าง เมื่อต้องทำงานมากกว่า 1ขั้นตอน
การใช้ Callback แบบนี้ทำให้โค้ดดูยาก และถูกเรียกว่า Callback Hell
const url1 = "kong.dev/file1.json" const url2 = "kong.dev/file2.json" const url3 = "kong.dev/file3.json" function dowloading(url, callback) { console.log(`กำลังดาวโหลด ${url}`) setTimeout(() => { callback(url) }, 3000) } dowloading(url1, (result) => { console.log(`ดาวโหลด ${result} เรียบร้อย!`) dowloading(url2, (result) => { console.log(`ดาวโหลด ${result} เรียบร้อย!`) dowloading(url3, (resutl) => { console.log(`ดาวโหลด ${result} เรียบร้อย!`) }) }) })
กำลังดาวโหลด kong.dev/file1.json ดาวโหลด kong.dev/file1.json เรียบร้อย! กำลังดาวโหลด kong.dev/file2.json ดาวโหลด kong.dev/file2.json เรียบร้อย! กำลังดาวโหลด kong.dev/file3.json ดาวโหลด kong.dev/file2.json เรียบร้อย!
Promise (พรอมิส)
ถูกนำมาใช้งานแบบ Asynchronous คือ ให้รอในระหว่างที่ผลลัพธ์ยังไม่เกิดขึ้น ใช้กับงานที่มีการหน่วงเวลา และแก้ปัญหา Callback hell
การสร้าง Promise
Promise(function (resolve, reject) { })
CallBack Function – ใช้กำหนดการกระทำบางอย่าง
การทำงานใน Promise จะมี 3 สถานะ pending, resolve, reject
- pending : เป็นสถานะเริ่มต้อนของ Promise
ถ้าทำงานสำเร็จจะเป็น resolve
ถ้าล้มเหลวจะเป็น reject - resolve/fulfilled : เป็นพารามิเตอร์ของ callback ซึ่งใช้กำหนดสถานะหากทำงาน “สำเร็จ”
- reject : เป็นพารามิเตอร์ของ callback ซึ่งใช้กำหนดสถานะหากทำงาน “ผิดพลาด”
let connect = true const dowloading = new Promise(function (resolve, reject) { if (connect) { resolve("ดาวน์โหลดเสร็จเรียบร้อย") } else { reject("เกิดข้อผิดพลาดระหว่าง Download") } })
ตัวอย่างการใช้งานกับ setTimeout
let connect = true const dowloading = new Promise(function (resolve, reject) { setTimeout(() => { if (connect) { resolve("ดาวน์โหลดเสร็จเรียบร้อย") } else { reject("เกิดข้อผิดพลาดระหว่าง Download") } },3000) })
เมธอด then(), catch(), finally()
การทำงานของ Promise ระหว่างที่ตรวจสอบสถานะของ Promise อยู่ว่าเป็น resolve หรือ reject สามารถกำหนดขั้นตอนต่อไปในการทำงานได้โดยอาศัย then(), catch() มาใช้ตอบสถานะดังกล่าว
- then() : ใช้งานร่วมกับสถานะ resolve หรือเมื่อ Promise ทำงานสำเร็จ
- catch() : ใช้งานร่วมกับสถานะ reject หรือเมื่อ Promise ทำงานผิดพลาด
- finally() : ไม่ว่าผลลัพธ์ของสถานะจะเปนอย่างไร ให้ทำงานต่อส่วนนี้ได้เลย
let connect = true const dowloading = new Promise(function (resolve, reject) { // }) dowloading.then(result=>{ // }) dowloading.catch(result=>{ // })
หรือแบบลดรูป ต่อท้าย
let connect = true const dowloading = new Promise(function (resolve, reject) { // }).then(result=>{ // }).catch(result=>{ // })
ตัวอย่าง
const connect = true const url1 = "kong.dev/file1.json" function dowloading(url) { return new Promise(function (resolve, reject) { console.log(`กำลังโหลด ${url}........`); setTimeout(() => { if (connect) { resolve(`โหลด ${url} เรียบร้อย`); } else { reject('เกิดข้อผิดพลาด'); } }, 3000) }) } dowloading(url1).then(result => { console.log(result); }).catch(err => { console.log(err); }).finally(() => { console.log('จลการทำงาน'); })
connect = true กำลังโหลด kong.dev/file1.json........ โหลด kong.dev/file1.json เรียบร้อย จลการทำงาน connect = false กำลังโหลด kong.dev/file1.json........ เกิดข้อผิดพลาด จลการทำงาน
ตัวอย่างการ then แบบที่ 1 : Promise Hell
const connect = true const url1 = "kong.dev/file1.json" const url2 = "kong.dev/file2.json" const url3 = "kong.dev/file3.json" function dowloading(url) { return new Promise(function (resolve, reject) { console.log(`กำลังโหลด ${url}........`); setTimeout(() => { if (connect) { resolve(`โหลด ${url} เรียบร้อย`); } else { reject('เกิดข้อผิดพลาด'); } }, 3000) }) } dowloading(url1).then(result => { console.log(result); dowloading(url2).then(result => { console.log(result); dowloading(url3).then(result => { console.log(result); }) }) })
กำลังโหลด kong.dev/file1.json........ โหลด kong.dev/file1.json เรียบร้อย กำลังโหลด kong.dev/file2.json........ โหลด kong.dev/file2.json เรียบร้อย กำลังโหลด kong.dev/file3.json........ โหลด kong.dev/file3.json เรียบร้อย
ตัวอย่างการ then แบบที่ 2
const connect = true const url1 = "kong.dev/file1.json" const url2 = "kong.dev/file2.json" const url3 = "kong.dev/file3.json" function dowloading(url) { return new Promise(function (resolve, reject) { console.log(`กำลังโหลด ${url}........`); setTimeout(() => { if (connect) { resolve(`โหลด ${url} เรียบร้อย`); } else { reject('เกิดข้อผิดพลาด'); } }, 3000) }) } dowloading(url1).then((result)=>{ console.log(result); return dowloading(url2) }).then((result)=>{ console.log(result); return dowloading(url3) })
กำลังโหลด kong.dev/file1.json........ โหลด kong.dev/file1.json เรียบร้อย กำลังโหลด kong.dev/file2.json........ โหลด kong.dev/file2.json เรียบร้อย กำลังโหลด kong.dev/file3.json........
async await ใช้คู่กับ Promise
const connect = true const url1 = "kong.dev/file1.json" const url2 = "kong.dev/file2.json" const url3 = "kong.dev/file3.json" function dowloading(url) { return new Promise(function (resolve, reject) { console.log(`กำลังโหลด ${url}........`); setTimeout(() => { if (connect) { resolve(`โหลด ${url} เรียบร้อย`); } else { reject('เกิดข้อผิดพลาด'); } }, 3000) }) } async function start (){ console.log(await dowloading(url1)); console.log(await dowloading(url2)); console.log(await dowloading(url3)); } start ()
กำลังโหลด kong.dev/file1.json........ โหลด kong.dev/file1.json เรียบร้อย กำลังโหลด kong.dev/file2.json........ โหลด kong.dev/file2.json เรียบร้อย กำลังโหลด kong.dev/file3.json........ โหลด kong.dev/file3.json เรียบร้อย
สำหรับท่านที่สนใจ แนะนำเข้าไปดูคลิปสอบ ของท่าน KongRuksiam
ได้ตามลิ้งด้านล่างครับ อันนี้ผมแค่โน๊ตไว้กันลืมครับ
รู้จักกับ Callback , Promise , Async / Await | JavaScript จบในคลิปเดียว
KongRuksiam Official