🎞️ Videos → Supercharge Your JavaScript Promises
Description
มาทำความเข้าใจเกี่ยวกับ promise ใน JavaScript ให้กระจ่างยิ่งขึ้นกับเซสชั่นนี้ ผู้บรรยายจะพาคุณสำรวจตั้งแต่พื้นฐานการทำงานของ promise, then, catch, และ finally พร้อมเจาะลึกปัญหาที่พบบ่อยในการใช้งานจริง เช่น การลืม return ใน then, การจัดการ promise หลายตัวด้วย Promise.all และ Promise.allSettled รวมถึงการ debug โค้ดที่มักเกิดขึ้นกับ junior และ senior developer นอกจากนี้ยังแนะนำ library ที่เป็นประโยชน์อย่าง promise-retry และ promise-pool สำหรับการจัดการสถานการณ์เฉพาะ เช่น การ retry API request และการควบคุม rate limit มาร่วมเรียนรู้และแลกเปลี่ยนประสบการณ์การใช้ promise ใน JavaScript เพื่อเขียนโค้ดได้อย่างมีประสิทธิภาพมากขึ้น
Chapters
- เกริ่นนำและแนะนำตัว: สัญญาใน JavaScript 0:00
- ทำความเข้าใจ Promise: สัญญาของ JavaScript 0:31
- ปัญหาโลกแตก: การใช้ Promise ในโปรเจคใหญ่ 1:08
- ตัวอย่างโค้ดเบสิกของ Promise 1:29
- Resolve, Reject, Then, Catch, Finally: เส้นทางของ Promise 2:50
- Promise Chaining และปัญหาการ Return ค่า 4:26
- ความสำคัญของ Return ใน Promise Chaining 6:01
- Await: การรอ Promise ให้ทำงานเสร็จ 7:01
- ปัญหาของ Then ที่มากเกินไปและการแก้ไขด้วย Return 9:54
- Promise หลายตัว: Promise.all และ Promise.allSettled 11:01
- Promise.any: ตัวไหนเร็วสุด ตัวนั้นได้ไป 14:03
- Error Handling ใน Promise: Retry และ Pool 15:04
- RxJS และ Promise Retry: ตัวช่วยสำหรับ Retry 17:50
- สรุปและ Q&A 18:38
- Q&A: Async Await ใน MVC Architecture 19:50
- Q&A: Readability และ Error Tracing ใน Async Await 24:10
- แจกตั๋ว JetBrains และขอบคุณผู้บรรยาย 25:41
Transcript
คำบรรยายต่อไปนี้อาจไม่ถูกต้องทั้งหมด หากคุณพบข้อผิดพลาดใดๆ คุณสามารถช่วยแก้ไขข้อผิดพลาดได้บน GitHub
เกริ่นนำและแนะนำตัว: สัญญาใน JavaScript0:00
โอเคครับ สวัสดีครับผม
ก็เป็นคนแรกเลยนะครับ โอเคก็สไลด์พึ่งเสร็จนะครับ จริงๆ สไลด์เยอะมากนะครับ แต่ก็ต้องตัดออกเพราะว่าน่าจะโค้ดเยอะไปนะครับ เลยเดี๋ยวใช้วิธีการเน้นคุยดีกว่านะครับ ก็ตอนนี้ก็เหลือแค่ 16 สไลด์นะครับ กับประมาณ 20 นาทีเนาะ ครับก็สวัสดีทุกคนนะครับ ที่มา BKK.JS นะครับรอบนี้
ทำความเข้าใจ Promise: สัญญาของ JavaScript0:31
สำหรับเซคชั่นของผมนะก็คือจริงๆ เป็นเรื่องเรียบง่ายมากนะครับ ถ้าใครอยู่ในสายของ JavaScript อยู่แล้วเนี่ย ก็คงจะรู้จักสิ่งที่เรียกว่า promise เนาะ เนาะหรือว่าที่เราแบบหลายปีที่ผ่านมาเรารู้จักเรื่องแบบ เอ้ยเราจะทำตามสัญญาใช่มั้ย อันเนี้ยเราจะมาคุยเรื่องสัญญาของ JavaScript เนาะ
ให้เข้าใจตรงกันก่อนว่า เอ้ยโอเคมันอย่างเงี้ย เราเข้าใจตรงกันมั้ยเนาะ แล้วตอนเซคชั่นสุดท้ายเนี่ย ผมจะมีเหมือนเป็นเคสที่ผมก็ชอบเถียงกับจูเนียร์ หรือแบบซีเนียร์คนอื่นเนาะ เวลาเราทำโปรเจคแบบใหญ่ๆ ด้วยกันว่า ไอ้ปัญหาที่เราเจอเราก็จะแก้ด้วยการใช้ promise ยังไงเนาะ
ปัญหาโลกแตก: การใช้ Promise ในโปรเจคใหญ่1:08
คือทุกคนใช้ promise เป็นเนาะ ถูกมั้ยครับ
ซึ่งผมก็คิดว่าผมก็ใช้เป็นนะ แต่ว่าซีเนียร์บางคนนะครับ ก็ใช้เป็นเนาะ แล้วใช้คนละวิธีกัน ซึ่งมันไม่มีใครถูกไม่มีใครผิดนะครับ เดี๋ยวเรามาดูกันว่าเราจะใช้กันแบบไหนเนาะ เพราะว่าแต่ละสถานการณ์เนาะมันจะไม่เหมือนกันนะครับ
ตัวอย่างโค้ดเบสิกของ Promise1:29
เรามาดูตัวอย่างเนาะ โค้ดนี้แบบเบสิกมากๆ เลยนะครับ ก็คือ promise เนาะมันจะลักษณะประมาณนี้ ถ้าตรงไหนผิดนะครับ บอกผมได้นะ ผมจะมีเหมือนโค้ดผิดอยู่ประมาณ 2-3 จุดนะครับ ถ้าใครแบบหาเจอเนี่ยก็แสดงว่า คุณเนี่ยเหมือนผมเลยนะครับ
เพราะงั้น promise มันมีแค่นี้ ก็คือว่าหลักการของมันเนาะ จริงๆ promise ต้องพูดกับ asynchronous await เนาะ แต่ว่าผมจะโฟกัสที่ promise อย่างเดียวเนาะ เพราะว่าเดี๋ยวมันจะยาวเกินนะครับ ก็หลักๆ เนาะคือ promise มันคือแค่นี้เนาะ มีพารามิเตอร์ 2 ตัวคือ resolve กับ reject ใช่มั้ยครับ แล้วก็เขียนโค้ดของเราไปเนาะ นั่นหลักการมันมีอยู่แค่นี้ถูกมั้ยครับ ถ้าเราดู full code หน่อยก็คือ เราจะเอา promise เนี่ยไปทำอะไรบางอย่างใช่มั้ย ไม่ว่าจะเป็น asynchronous code หรือว่าโค้ดทั่วๆ ไปเนาะ
ถ้าสุดท้ายแล้วผลลัพธ์มันเป็นสิ่งที่เราหวังเนาะ
เราได้ผลที่เราหวังอย่างเช่น เราต้องการต่อ API ใช่มั้ย เราต้องการต่อ HTTP ใช่มั้ย เราต้องการต่อ Salesforce ต้องการต่อ SAP ใช่ป่ะ คือผมต่อแทบจะทุกอย่างนะ มันต่อสำเร็จเนาะตามที่เราหวังอะ สิ่งที่เกิดขึ้นก็คือเราจะเอาไปใส่ใน resolve ถูกป่ะ
แล้วถ้ามันเกิดอะไรที่แบบผิดหวังอะ สัญญาแล้วไม่เป็นสัญญาใช่ป่ะ ผิดหวังอะ เราจะเอาไปใส่ใน reject ถูกป่ะ เพื่อให้มัน reject ออกไปถูกมั้ย
Resolve, Reject, Then, Catch, Finally: เส้นทางของ Promise2:50
จริงๆ อะคอนเซ็ปต์เบสิกอะมันมีอยู่แค่นี้ใช่มั้ยครับ ทีเนี้ยสิ่งที่ใส่ไปใน resolve มันจะไปโผล่อยู่ที่นึงใช่มั้ยครับ สิ่งที่ใส่ไปใน reject อะ มันจะไปโผล่อยู่ที่นึง สมมติถ้ารันโค้ดบรรทัดแถวๆ นี้นะ
จากที่เห็นเลยนะ คิดว่ามีบั๊กมั้ย
ถ้าเรา console.log ออกมาครับ เราคิดว่าเราจะได้เมสเสจอะไรนะ จากคนที่ใช้เป็น แบบ compile โค้ดโดยที่ไม่ต้องเขียนโค้ด นี่เขียนด้วยกระดาษเลย compile ในหัวนะ แบบหลักสูตรที่เราจะต้องเจอนะ คิดว่าเราจะเกิดอะไรขึ้นครับ ไอ้ console.log มันจะเกิดอะไรขึ้น ได้ผลลัพธ์มั้ย ได้ undefined อะใครคิดว่าได้ undefined ครับ โอเคใครคิดว่าได้ promise object
โอเคคือเคสเนี้ย มันจะได้ promise object เนาะ เพราะว่าอะไรครับ ก็คือ promise ปุ๊บมัน console.log เลยถูกมั้ย คือไอ้ promise มันยังไม่ทำงานถูกป่ะ เพราะว่ามันก็คือเหมือนเป็นหลักการของมันก็คือ เราสัญญาว่าเราจะทำให้มันเสร็จเนาะ ใช่มั้ยครับ แล้วมันก็คือข้ามไปทำงานอย่างอื่นเลยต่อถูกมั้ยครับ แสดงว่าไอ้จังหวะเนี้ย ถ้าเราไม่ได้แบบทำอะไรกับมันเพิ่มอะ ไอ้ตัว promise อะมันจะได้ object ที่ชื่อว่า promise มาถูกมั้ย ซึ่งมันก็มี 2 แบบคือ promise ที่ pending ถูกมั้ย
ลองนึกภาพตามนะผมตัดสไลด์ออกไปเยอะ ก็คือเป็น pending ถูกมั้ย เป็น fulfilled ใช่ป่ะ อันสุดท้ายเป็นอะไรครับที่เป็นไปได้ เป็น rejected ถูกมั้ย มี 3 อย่างขอบคุณมากครับผม น่ารักเนาะ
Promise Chaining และปัญหาการ Return ค่า4:26
ทีนี้เนี่ยสมมติว่าเราบอกว่าเรารองรัน promise เนาะ แบบที่ 1 เนาะ กับรัน promise แบบข้างล่างเนาะ สมมติว่าถ้าเรารันแบบเนี้ยครับ เนี่ยรันโค้ดนี้ออกมา เราคิดว่า log data 1 กับ log data 2 อะ มันเหมือนกันมั้ย หรือมันต่างกัน
คิดว่าเหมือนกันมั้ย ไม่เหมือนหรอ คิดว่าแบบบนถูกหรือแบบล่างถูกครับ หรือทั้ง 2 แบบก็ถูกเหมือนกัน
โหทุกคนไม่ให้ความร่วมมือเลยอะ โหชีวิตคนแรกทุกคนตื่นยัง
อันนี้คือให้กำลังใจ โอเคนะก็คือถ้าจากที่เห็นเนาะ คือสมมติว่าเนี่ยก็คือแพทเทิร์นจะประมาณนี้แหละ ก็คือมันจะมีแค่ 3 เซคชั่นเนาะถ้าเอาเข้าใจง่ายๆ เนาะ ก็คือมันจะมีแค่เซคชั่นที่เป็น promise เมื่อกี้เนาะ ที่เราสร้างไว้ใช่มั้ย จากนั้นเนี่ยเราบอกว่า ถ้ามันโดน resolve ถูกมั้ย ถ้ามันสิ่งที่เราหวังไว้อะ ที่เราตั้งใจไว้ว่ามันเสร็จแล้วอะ ผลลัพธ์มันจะมาเข้าที่ไหนครับ
มันจะมาเข้าที่ฟังก์ชัน then เนาะ หมายความว่าคุณโยนอะไรเข้าไปในรูของ resolve เรียกรูเลย
เราโยนอะไรเข้าไปในรูของ resolve เนาะ อันเนี้ยมันจะไปโผล่ตรงไหน โผล่ที่ then ถูกป่ะ แล้วถ้าเราโยนเข้าไปที่รูของ reject อะโผล่ที่ไหน
มันจะไปโผล่ที่ catch ถูกป่ะ สุดท้าย finally ครับ ทำงานตอนไหนครับ สุดท้ายเนาะ
ความสำคัญของ Return ใน Promise Chaining6:01
อันนี้คือเบสิกเนาะก็คือหมายความว่า จริงๆ แล้วเรา โอเคนะ จริงๆ แล้วเนี่ยเมื่อกี้คือเบสิกมากๆ เนาะ
คือหมายความว่า เดี๋ยวผมพูดไปเรื่อยๆ นะครับ โอเคก็ เมื่อกี้นี้น่าจะรู้กันอยู่แล้วเนาะ ก็คือเราสามารถนะครับ resolve กับ reject ได้เนาะ ซึ่งผลลัพธ์เนี่ยมันก็จะเข้าออกตามที่เราคุยกันเมื่อกี้นี้นะครับ
เดี๋ยวสไลด์ต่อไปจะมีบั๊ก
แต่เรามาดูสไลด์นี้ก่อนนะครับ ถ้าสไลด์นี้สมมติว่าเอาโค้ดชุดนี้เนาะ รันออกมาครับ
ทุกคนรันในหัวคิดว่า ผลลัพธ์ data 1 จะเป็นอะไรครับ
รู้มั้ยครับ เดาได้มั้ย
Await: การรอ Promise ให้ทำงานเสร็จ7:01
เป็น promise เหมือนเดิมถูกมั้ย เป็น promise เนาะ data 1 เป็น promise แล้ว data 2 อะครับ จะเป็นไรครับ
จะเป็น now จริงป่ะครับ
จะเป็น undefined เฮ้ยสุดยอด รู้ป่ะ สมมติว่าถ้าเราไม่รันในโค้ดครับ เราพยายามเนาะ คืออย่างผมเนี่ยผมจะพยายามคุยให้เข้าใจก่อนว่า คุณเข้าใจแบบภาพเดียวกันกับสิ่งที่มันเป็นมั้ย คือถ้ามันสามารถความพายในหัวได้แล้วเรารู้อะ คือเราจะเข้าใจว่าจริงๆ มันก็มีอยู่เท่าเนี้ย มันจะไม่มีเหนือไปกว่าเนี้ย นึกออกป่ะ เออช่างมันเถอะนึกไม่ออกก็ไม่เป็นไรครับ โอเคคืออันเนี้ยมันจะได้เป็นไรครับ promise เนาะเพราะว่ามันโดนแค่แบบเหมือนกับโดนเขียนโค้ด ใช่ป่ะ data 1 เนาะ data 1 อะเก็บไรครับ promise เนาะ เวลาเรา print log ออกมาตรงเนี้ย เราจะยังไม่ได้ data ถูกป่ะ เพราะว่า promise มันยังทำงานไม่เสร็จถูกมั้ย เออมันจะข้ามไปเลยถูกมั้ย อะแต่ว่าพอเราบอกว่า data 2 เนี่ยเราสั่งให้มัน await ใช่ป่ะ
อันเนี้ยมันจะรอ รอไรครับ รอ promise ถูกมั้ย ให้มัน resolve สำเร็จ ซึ่ง resolve สำเร็จเนี่ย มันก็มี 2 แบบ ก็คือ resolve ได้ใช่มั้ย กับ reject ถูกป่ะ
เออซึ่งถ้าในเคสเนี้ย resolve ได้ปุ๊บอะ มันก็จะได้ data ออกมาถูกมั้ย แต่ data 2 มันไม่มีเพราะไรครับ เพราะว่าตำแหน่งของ then น่ะ เห็นป่ะมันไม่มี return อะไรเลย ก็แสดงว่าตัวแปร data 2 เนี้ยมันไม่ได้อะไร มันไม่ได้รับอะไรเข้ามามันก็จะกลายเป็น undefined ถูกป่ะ อะ ถ้าเราจะแก้โค้ดสมมตินะ เราจะแก้โค้ดบรรทัดเนี้ย ให้ไอ้ตัว data 2 มันมีค่าครับ เราต้องเพิ่มอะไร
เพื่อให้ promise ของเรามันเป็นไปตามที่มันควรจะเป็นครับ
รู้มั้ยเราเพิ่มไรไปใช่มั้ย ตามกฎแล้วก็คือเราควรจะเพิ่ม return เข้าไปตรงนี้ถูกมั้ย คือหมายความว่า ถ้า resolve สำเร็จใช่ป่ะ data จะไหลมาที่ไหน ไหลมาที่ then ถูกมั้ย พอไหลที่ then ปุ๊บเราต้องเขียน return ใน then เพื่อให้มันไหลออกมาจาก promise อีกทีนึง ซึ่งไอ้การไหลออกมาจาก promise น่ะมันคือ เนี่ยรอแล้วก็ไหลเข้ามาที่ตัวแปร 2 ถูกป่ะ เออแล้วจังหวะตัวแปร 2 เนี่ยเรา console.log ออกมาครับ เราจะได้ data นึกออกป่ะ เพราะฉะนั้นน่ะส่วนใหญ่ที่ผมทะเลาะกับ junior หรือว่า senior บางคนนะ ก็คือ debug แล้วไม่เจอบั๊ก เพราะว่าไม่รู้คำตอบว่าทำไมมันไม่มีข้อมูลออกมา นึกออกป่ะ เพราะว่าเราคิดว่าโค้ดมันถูกนะ compile ก็ผ่านเนาะ แต่ว่าสิ่งที่เราหายไปก็คือ return ถูกมั้ย
ปัญหาของ Then ที่มากเกินไปและการแก้ไขด้วย Return9:54
อะ ทีนี้มันมีอีกปัญหานึงนะครับที่เราเจอก็คือ เรามี then ค่อนข้างเยอะ เรามีหลาย then ใช่มั้ย อันนี้เราถ้าเราเจอเคสแบบเนี้ย เราก็คิดว่าข้อมูลจะเป็นยังไงครับ รู้มั้ยครับ
อันนี้คือเวลาที่เหลือหรอ
ที่ผ่านไป 10 นาทีแล้วหรอ เฮ้ยไม่ทันแล้วอะโอเค ก็คือ then นะครับก็คือ resolve แรกเนาะ then อันแรกจะไหลเข้ามาหาไรครับ ไหลมาหาอันที่ 2 ถูกมั้ย และอันที่ 2 เนี่ยถ้าไม่มีอะไรเกิดขึ้นปุ๊บมันก็จะไรครับ ไป finally ถูกมั้ย เออ เคสเนี้ย เหมือนเดิมเลยก็คืออันเนี้ยมีบั๊ก บั๊กตรงไหนครับ ไม่มี return ถูกมั้ย ก็คือถ้าเราไม่มี return แปลว่า resolve อันแรกอะ มันจะไม่ไหลมาหา resolve ที่ 2 ถูกป่ะ เพื่อทำไรบางอย่าง แล้ว resolve ที่ 2 อะก็จะไม่ไหลไปหาที่ ก็คือไหลมาหาเนี้ย แล้วมันก็จะไม่ออก console.log เหมือนเดิม เพราะว่ามันไม่มี return อันนี้งงมั้ย
อะงงก็ปล่อยมันไปนะครับ ผมว่าจะมีปัญหากับผมคนเดียวนะครับ โอเคอะ ทีนี้ครับ
Promise หลายตัว: Promise.all และ Promise.allSettled11:01
สิ่งที่เราชอบใช้กันเนาะ ก็คือเมื่อกี้เนี้ยเป็นแบบพูดถึง basic ทั่วๆ ไปเนาะ คือบางคนอาจจะเข้าใจอยู่แล้วเนาะ แต่ว่าอยากจะให้ลองจินตนาการว่า ถ้าแบบเราลืมอะไรไปบางอย่างเนี่ย ก็คือผลลัพธ์ที่เกิดขึ้นมันควรจะเป็นอะไรเนาะ ซึ่งผมก็ตีกับน้อง junior บ่อยๆ นะครับว่า
เนี่ยแหละคือเหตุการณ์ที่เกิดขึ้นเนาะ ทุกคนอาจจะรู้อยู่แล้วอะ ทีนี้เดี๋ยวเรามาดูต่อครับ ก็คือเมื่อกี้เนี้ยที่เรารันก็คือเป็น promise 1 ตัวใช่มั้ยครับ เออแล้วเราใส่ await ก็คือรอใช่ป่ะ แล้วถ้าเรามี promise หลายๆ ตัวอะใช่มั้ยครับ เรา await มันทุกตัวอะก็แปลว่ามันจะรอ ใช่ป่ะ
รอไปตัวนึงเสร็จ ทำตัว 2 ตัว 2 เสร็จทำตัว 3 ถูกมั้ยครับ
อืมทีนี้บางคนเค้าบอกว่าใช้เนี่ยเราจะใช้อะไรครับ Promise.all เพื่ออะไรรู้มั้ย
สมมติว่าเรามี promise 3 ตัวเนาะ อะ promise 3 ตัวเราอยากให้ไอ้ 3 ตัวเนี้ย จริงๆ คือมันไม่มีความเกี่ยวข้องกันเลยนะ ยกตัวอย่างเช่นนะครับ อ่าผมทำหน้าจอขึ้นมา 1 หน้าจอเนาะ หน้าจออะมี dropdown list อยู่ 3 ตัว ถามว่า dropdown list 3 ตัวเนี่ยมันจำเป็นต้องรอกันมั้ย ไม่ต้องถูกป่ะ เออเราจะใช้วิธีประมาณนี้เนาะ ก็คือ promise ตัวแรกยิง API เส้นที่ 1 ถูกมั้ย ไปดึง dropdown มา ดึงเส้นที่ 2 ดึงเส้นที่ 3 มาใช่ป่ะ มันอยู่แบบนี้ใช่มั้ย แต่ถ้าเราบอกว่าเราแต่ละตัวเรา await await await เหมือนเมื่อกี้เนี้ย มันก็จะกลายเป็นว่ามันรอแต่ละตัวเสร็จถูกมั้ย ซึ่งตัวสุดท้ายอาจจะเสร็จก่อนก็ได้ใช่ป่ะ เพราะฉะนั้นน่ะโดยปกติแล้วเราจะใช้คำว่า Promise.all เนาะ
เข้าไปเพื่อบอกว่ารัน 1 2 3 อะ พร้อมกันเลย เนาะ รันพร้อมกันเลย พอรันพร้อมกันเสร็จแล้วปุ๊บเนี่ย ผลลัพธ์ที่ได้เนี่ยมันจะออกมาที่ then ถูกมั้ย เนาะได้เป็น array ก็คือเนี่ยยกตัวอย่างนะครับ 1 2 3 เนาะ แต่มันยังมีเหตุการณ์แบบนี้ครับ สมมติว่า ลิงก์แรกเนาะ API แรกพัง
พังด้วยเหตุผลอะไรไม่รู้ใช่มั้ย มันพัง
อะ สิ่งที่เกิดขึ้นคืออะไรรู้ป่ะ อะ ตำแหน่งแรกจะเกิดไรขึ้นรู้ป่ะ รู้มั้ย อะไรเกิดไรครับ
อันนั้นจะกลายเป็น reject แล้วก็ 2 3 ได้ data เหมือนเดิมถูกไหม
จริงๆ ไม่ใช่นะ จริงๆ ก็คือเนี่ยมันดูเหมือนจะใช่แต่จริงๆ มันยังไม่ใช่ ไอ้คำว่า all เนี่ยมันแปลว่ามันทำทุกตัวก็จริงนะ ถ้าทุกตัวสำเร็จอะเราได้ data นะ แต่ถ้ามีตัวใดตัวนึง fail อะ แม่งยกกระบุง fail หมดเลยนะถูกไหม อันเนี้ยก็เป็นบั๊กที่ผมเถียงกับน้องจุ๊เนี่ยเหมือนกัน ว่าเฮ้ยเขียนแบบเนี้ยไม่ได้บางทีนะมันไม่ได้เนาะ อีกเคสนึงถ้าบอกเอ้าแล้วพี่ถ้าผมอยากจะได้ล่ะ ผมอยากจะให้มันยิงทุกตัวเลย จะ fail ไม่ fail ไม่รู้ใช่ปะ เราใช้ตัวนี้ช่วย เคยเห็นปะ
ไอ้เนี่ยคือมันบอกว่ามันไม่สนใจนะว่าจะ fail หรือจะ success ใช่ปะ
ก็คือไอ้ตรงเนี้ยเหมือน all เมื่อกี้ ก็คือยิงพร้อมกันหมดเลยแต่ว่ามันจะไม่ตายถ้ามัน fail เนาะ อันนั้นคือมันยิงทุกตัวครับ แล้วเอาผลลัพธ์มาบอกเรา นี่คือความต่างมีแค่นี้เนาะ
Promise.any: ตัวไหนเร็วสุด ตัวนั้นได้ไป14:03
คือสมมติว่าถ้าเราบอกว่าเราซีเรียสว่ายิงทุกตัวอะ มันมีโอกาสที่จะ fail กับไม่ fail ใช่มั้ย อย่างเช่นอะไรครับ มีใครบอกได้บ้าง API อะไม่ค่อยเจอหรอก แต่มันมีอันที่ผมเจอบ่อยมากเลยคือพวกต่อ FTP ใช่ปะ
มันเป็นอะไรที่แบบว่าต่อครั้งแรกได้ ต่อครั้ง 2 ไม่ได้ ต่อครั้ง 3 ได้ ต่อครั้ง 4 5 6 ไม่ได้เพราะว่า connection มันจะเต็มอยู่ถูกปะ เพราะฉะนั้นน่ะ ถ้าเราใช้ all ปุ๊บอะ บางทีคือมันจะ fail แบบ fail หมดเลยใช่ปะ บางทีคือมัน fail แบบ fail บางตัว แล้วก็แบบโปรแกรมมันจะเพี้ยนๆ อะไรอย่างเงี้ยครับ เพราะฉะนั้นน่ะเราจะต้องใช้ตัวนี้ช่วยในการเช็กว่า มันต่อได้ครบไหมแล้วแต่ละตัว status เป็นอะไรเนาะ โอเคครับ เข้าใจใช่ไหม
ตัวนี้ครับตัวนี้อันนี้จริงๆ ผมไม่เคยใช้เลยนะ
อันเนี้ยก็คือหมายความว่าตัวไหนเร็วสุดอะครับ ตัวนั้นน่ะได้ data ไป เวลาจะหมดแล้วผมพูดเยอะเกินไป
Error Handling ใน Promise: Retry และ Pool15:04
ทีนี้สิ่งที่ผมเจอนะเจอแบบบ่อยๆ เลย ก็คือเวลาใช้ promise อะ เราเคยเจอ error แบบนี้ไหม ก็คือ request ใหญ่เกินไปใช่ปะ rate limit เนาะ
error 500 ใช่มั้ย bad gateway ใช่มั้ย service พวกเนี้ยก็คือพัง 505 นี่เคยเจอไหม
518 โอเค ไม่เคยเจอเหมือนกันอะ เพราะฉะนั้นน่ะก็คือสิ่งที่ผมจะบอกเนาะ ก็คือเมื่อกี้เนี่ยเรารู้อยู่แล้วแหละ อาจจะไม่รู้บางอย่างเนาะ แต่ว่าสิ่งที่จะมีตัวช่วยให้เราทำได้เนาะ เนื่องจากเวลาผมจะหมดแล้วผมขอเร็วๆ แล้วกัน ก็คือมันจะมีตัวสิ่งที่เรียกว่า promise retry เนาะ ตัวเนี้ยก็คือเป็น lib ที่ผมมาชอบให้น้องจุ๊เนี่ยลองใช้ดู คือในกรณีที่เรายิง API ไปแล้วใช่มั้ย มัน fail รอบที่ 1 ใช่ปะ เราจะ handle ยังไงครับ ไม่รู้ถูกไหม เราต้องเขียนอะไร ยิงรอบที่ 2 มั้ย ยิงรอบที่ 3 มั้ยถูกไหม ซึ่งเราไม่มีทางรู้ว่ามันจะ success เมื่อไหร่ถูกปะ เพราะฉะนั้นไอ้คำว่า retry เนี่ยมันจะช่วยเราได้ ก็คือเราแค่เอาคำว่า promise retry ไปครอบ ไปครอบสิ่งที่เราอยากจะให้มันรันก็คือตรงนี้เนาะ ดู something ตรงนี้ ก็คือเราบอกว่าตรงเนี้ย ปกติ default มันคือจะ retry ประมาณ 10 รอบ
แต่เราตั้งมันได้ ก็คือแปลว่าสมมติรอบแรกยิง FTP ไม่ได้ใช่ปะ connect ไม่ได้ใช่ปะ ตรงเนี้ยมันจะ retry ของมันเอง รอบ 2 รอบ 3 จนกว่ามันจะ connect ได้แล้วมันก็จะต่อ เพราะฉะนั้นน่ะ น้องไม่ต้องไปเขียน promise 1 2 3 4 5 พี่ผมจับไว้ 5 รอบ ต่อได้ชัวร์ใช่มั้ย มันอาจจะรอบที่ 6 ก็ได้ที่ต่อได้ใช่ปะ โอเคครับ อีกตัวนึงครับจะเป็น promise pool อันนี้ อันนี้คุ้นๆ ไหมครับ promise pool รู้จักไหม เคยมีใครเคยใช้ promise pool บ้าง เคยไหมครับ
ไม่เคยใช่มั้ยอะ คืออันเนี้ยปัญหาที่ผมเจอ คือสมมติว่าเราต้องการจะใช้ promise อะในการดึงเพจที่ 1 ถูกไหม ดึงเพจที่ 1 มา ปกติบนหน้าจอเราทำเพจ 1 เพจ 2 เพจ 3 ได้ถูกปะ แต่ว่าบางทีเราบอกว่าเราอยากจะ export data ออกมา สมมติ data มีอยู่ 1,000 รายการแล้วกัน
ต้องยิงวนยิง promise อะ กี่รอบดีอะ
10 รอบใช่ปะ 10 รอบปุ๊บอะ เราเขียน promise 10 ตัวอะเกิดอะไรขึ้น บางทีอะมันไปชน rate limit ถูกไหม ชน rate limit ก็คือ AWS แม่งล็อกไปเลยว่า rate limit คือห้ามยิงเกินกี่ตัวต่อวินาทีถูกปะ ปัญหาก็คือเราจะยิงไม่ได้ใช่มั้ย เพราะฉะนั้นวิธีการก็คือเราจะใช้ตัวเนี้ยช่วย ช่วยในการทำเหมือนสร้าง pool ขึ้นมา เพื่อบอกว่าเฮ้ย ยิงทีละ 2 ตัวเนาะ คือยิงทีละ 2 ตัว ตัวใดตัวนึงเสร็จอะ เอาตัวที่ 3 มาเสียบ ตัวที่ 3 เสร็จเอาตัวที่ 4 มาเสียบ แต่ว่าในขณะเดียวกันน่ะมันจะยิงแม่ง 2 ตัวเสมอ อันเนี้ยเราจะสามารถหลบ rate limit ได้ใช่ปะ บางทีบอกว่าเฮ้ยมึงก็ไปบอก infra ดิ ให้ infra เปลี่ยน rate limit โอ้ มึงกล้าคุยกับเค้าไหมล่ะ
RxJS และ Promise Retry: ตัวช่วยสำหรับ Retry17:50
ต่อมาครับก็เป็นเรื่องของอันเนี้ย ใครชอบใช้ RxJS หรอ มีเหมือนกันคือผมจะบอกว่ามันมีเหมือนกันนะครับ ก็คือใช้ในเคสเดียวกันนะครับ ตัวนี้นะครับ เหมือนกัน ก็คือเมื่อกี้ promise ใช่มั้ยเราเอา promise ไปครอบใช่ปะ ถ้าใครใช้ RxJS ก็คือเอา RxJS ไปครอบเหมือนกันเนาะ แต่แค่ lib เนี้ยมันจะช่วยทำให้เราไม่ต้องไปนั่งพะวง ว่ามันยิงรอบแรกได้ ยิงรอบ 2 ได้ รอบ 3 ไม่ได้อะไรอย่างเงี้ยใช่ปะ เราใช้วิธีเนี้ยในการทำ ซึ่งอันเนี้ยมันเป็น lib ที่มีอยู่แล้วนะครับ ก็คือเราสามารถ setting ได้เลยว่า เราอยากให้ยิงแบบกี่รอบ หรือยิง 1 รอบไม่ได้ใช่ปะรอ 5 วินาที
รอบ 2 ไม่ได้รอ 10 วินาที รอบ 3 ไม่ได้รอ 20 วินาทีอย่างเงี้ย
ไปอ่าน doc เอาเองนะครับ หมดแล้วอะ หมดรึยัง ยัง โอเค
สรุปและ Q&A18:38
นะครับ ผมว่าผมหมดแหละ ประมาณนี้ครับ ที่อยากจะมาแชร์นะก็คือเป็นปัญหาโลกแตกแหละ ที่แบบใครใช้ promise ก็ต้องเจอเนาะ แล้วก็จะต้องทะเลาะกับน้อง dev อะไรอย่างเงี้ย ว่าแบบเฮ้ยโปรแกรมมันหน่วงโปรแกรมมันช้าอะไรเงี้ยนะครับ ก็ใช้พวกเนี้ยช่วยได้ โอเคครับ
ครับ
ครับผม ก็ขอขอบคุณนะครับ พี่พีพีนะครับ ที่มาเล่าเรื่องของ promise นะครับผม
แล้วก็มีเทคนิคต่างๆ ครับ ผมมีแบบการ retry การหลบ rate limit นะครับผม ต่อไปนะครับ ก็จะเป็นสู่ช่วงของการทำ Q&A นะครับ ก็อย่าลืมนะครับ เรามี encouragement ให้ทุกคนถามตอบ เรามีตั๋ว JetBrains 1 ปีนะครับ สำหรับคนที่ถาม meaningful question เกี่ยวกับเรื่อง promise นะครับผม มีคำถาม Q&A ตรงไหนมั้ยครับผม มีใครมีคำถามมั้ยครับผม
มีคำถาม อาจจะไม่ได้เกี่ยวกับ promise ตรงๆ
Q&A: Async Await ใน MVC Architecture19:50
ก็เรื่องการใช้ async await อะครับ ก็คืออยากรู้ประมาณว่าเวลาเรามี 2 ฟังก์ชันเนาะ อันนี้พี่พอ ผมว่าพี่น่าจะมีความเข้าใจเรื่องของตัว MVC พวก repository level service level อะไรพวกนี้ สมมุติมีฟังก์ชัน A จะ call ฟังก์ชัน B ซึ่งผมบอกว่าฟังก์ชัน B เป็น async แล้วมีการใช้ await คำถามคือฟังก์ชัน A ที่ไป call ฟังก์ชัน B อะ จะต้องกลายเป็น async await ด้วยมั้ย เพื่อที่จะเอา resolve data ออกมา อันนั้นคือที่ผมเข้าใจ ทีนี้ระหว่าง คือมันมี 2 ท่า 1 คือ B return promise ตรงๆ กับ 2 ก็คือเป็น async await แบบที่ B level และที่ A level ด้วย แต่อยากรู้ว่ามันต่างกันแค่ไหนครับ ระหว่าง return promise ตรงๆ กับ async await ที่ low level
และไป async await ที่ high level ในจุดที่เราอยากจะได้ result ด้วย
พอเข้าใจคำถามอยู่แล้วครับ คือมันทำได้ 2 แบบเนาะ
เดี๋ยวผมอาจจะ ถ้าเป็นคำถามเนี่ย
เราน้องฝึกงานใช่มั้ย สมมุติ เคยเป็นน้องในทีมน้องฝึกงานอย่างงี้นะครับ ปกติผมก็จะบอกว่า คือถามว่าไอ้ตัวฟังก์ชันนั้นน่ะ มันได้ data เลยป่าว คือถ้าไม่ได้ data เลยใช่ป่ะ มันก็ไม่ต้องทำอะไร แต่ถ้ามันบอกว่า เฮ้ย อันเนี้ยมันต้องไป call API ใช่มั้ย มาได้ data มาก่อนใช่ป่ะ แล้วฟังก์ชันที่ 2 อะ มันต้องไป call FTP เพื่อได้ data เพื่อได้ connection มาก่อน แสดงว่าทั้ง 2 ตัว เราควรเปลี่ยน
เราอาจจะใช้ไอ้ตัวเนี้ยครับไปครอบเลย ถ้าถามผมนะ ก็คือไปครอบเนาะ เอาไปครอบเพื่อบอกว่า เฮ้ย ถ้าคุณ resolve ข้อมูลได้แล้ว
เราเอา data ที่ได้ไปหยอดใน resolve อันนั้นเราได้ data มาแล้ว 1 ก้อนใช่ป่ะ ส่วนอันที่ 2 อะครับ เราก็ให้มันไปต่อตัว FTP เนาะ
เพื่อให้ได้ resolve ออกมาเหมือนกัน ทีเนี้ย จุดเนี้ยเราก็ดูว่า เราสามารถรันพร้อมกันเลยได้มั้ย พร้อมกันเลยคือเหมือนว่า เราจำเป็นจะต้องใช้ข้อมูลอันแรกเพื่อเอาไปต่อ FTP มั้ย ถ้าไม่ใช่ใช่ป่ะ เราก็ยิงพร้อมกันไปเลย ก็คือใช้ไอ้ตัว all เมื่อกี้อะก็ได้ ก็คือให้มันยิงพร้อมกันไปเลย คือมึงดึงไฟล์ไป ก็คือขอโทษ ดึงข้อมูลไป ต่อ FTP ไป แต่ ณ จุดที่มันเสร็จพร้อมกันน่ะ เราถึงเอา 2 ฟังก์ชันนั้นมารวมกัน ก็เป็นวิธีที่สามารถเราลดเวลาได้ โอเค ถ้างั้นผมขออนุญาตเพิ่ม context บริบทก่อน สมมุติที่มี application นึงเนาะ ที่ service level ที่ code ฟังก์ชันที่ service level ที่ไป call ตัว repository ฟังก์ชันนึง ซึ่งเป็นการที่ตัว repository เนี่ย ก็คือไป call เอาข้อมูลจาก database เนาะ ซึ่ง ณ การรอข้อมูลน่ะ จะเกิดที่ repository level low level ข้างล่าง ทีนี้ service จะมา call ข้อมูลที่ผ่าน repository ครับ คำถามของผมก็คือว่า ถ้าท่าปกติที่ผมทำอะนะ ผมจะแปลงตัว service เป็น async await ด้วย เพื่อที่ว่าเราจะเอา data ที่ได้จาก database เนี่ย จากที่ผ่าน repository ขึ้นมาเนี่ย เอามารัน logic นู่นนี่นั่น แต่ว่ามันมีอีกท่านึง ก็คือ repository ไม่ต้อง await โยน promise ขึ้นมาเลย แล้ว service อะค่อยไป await หรือว่าจะไป then resolve ทีหลัง คือผมอยากรู้ว่า 2 ท่าเนี้ย ที่ prefer หรือว่ามี insight พอดีขอ share สักหน่อยได้มั้ย
ถ้าถามผมนะ ก็คือเป็นท่ายากเนาะ คือเป็นท่าที่มันยากขึ้นไปอีกหน่อยนึง ถ้าถามผมอะ จะเป็นท่าที่ 2 ก็คือ โยน promise มาเลย แล้วเอา promise ไปทำงานต่อในอีกฟังก์ชันนึงก็ได้ ก็คือไม่ต้องรอให้มันเสร็จใน level เนี้ยก็ได้ อันเนี้ยที่ผมเคยทำเนาะ ก็คือดูดไฟล์จาก FTP อะครับ แล้วก็พุ่งขึ้น S3 เลย เคสเนี้ยน่าจะใช้ท่าที่บอก ก็คือไม่ต้องรอให้ไฟล์อะโหลดเข้ามาในเครื่องใช่ป่ะ เราเหมือนกับจับ promise 2 ตัว ต่อ pipeline แล้วก็ให้มัน data stream ขึ้นไปทั้งหมดเลย แต่ว่าคือถ้าทำได้ก็โอเคเลยนะ เพราะว่ามันก็จะเร็วกว่าตอนที่โหลด data มามารอ แล้วเอา data ไปทำต่อ แต่ถามว่าแบบลง detail กว่าเนี้ย ก็คือมันยิบย่อยละ เหมือนกับว่า ผมว่าผมอาจจะตอบไม่ได้เต็มที่เนาะ แต่ถ้าแบบเคยทำอยู่แล้วแล้วมันเวิร์กอะ ผมคิดว่าแบบที่ 2 ที่พูดเมื่อกี้นะ น่าจะเร็วกว่า เร็วกว่าแบบมานั่งรอ data แรกกับ data 2
ถ้าเป็นอย่างงั้นนะ ท่าที่ 2 อะ ผมอะสงสัย
Q&A: Readability และ Error Tracing ใน Async Await24:10
อันนี้ขอเพิ่มนิดนึงละกันนะครับผม สงสัยแค่ว่า โอเค ตัวฟังก์ชันที่ repository ที่ return promise ไปอะ ปกติก็จะไม่ใส่ async mark ไว้ที่ฟังก์ชันเนาะ เพราะว่าพี่ return promise อยู่แล้ว แต่ว่าไอ้ตัวที่เรียกเป็น async อะไรเงี้ย มันจะทำให้เกิด อันนี้อาจจะเป็น preference ส่วนตัว เรื่อง readability ว่าเวลาอ่านมันจะงงมั้ย คือผมกำลังสงสัยอยู่ว่า โอเค คือปัญหาเนี่ย ของผมเนี่ย คือเรื่องของการ styling ของ code เนาะ
เรา async await ที่ low level high level มา call ฟังก์ชันที่เป็น async await ก็ต้องกลายเป็น async await ด้วย เพราะว่าจะเอา data ไปทำอย่างอื่นด้วยนู่นนี่นั่น แล้วทีเนี้ยผมก็เลยเจอปัญหาที่ว่า มันเป็น async await เต็มไปหมดเลย ขึ้นไปถึง level สูงสุดอะไรเงี้ย แต่ทีเนี้ยพอมาพูดถึงอีกท่านึงที่ผม propose ไป ที่ว่า return เป็น promise ปัญหาที่เกิดขึ้นก็คือ เวลา track มัน ไอ้พวก error เนี่ย มันก็จะ trace ไม่ได้ เพราะว่ามันไม่อยู่รอสักจุดเลย มัน return promise return promise เราไม่รู้ว่า data มันไปตายที่ตรงไหน เข้าใจครับ อันนี้เดี๋ยวน่าจะรบกวน speaker ท่านอื่น เดี๋ยวอันเนี้ยเราคุยกันส่วนตัวได้ code ของ JavaScript จริงๆ มัน simple นะ อันนี้ผมก็เถียงกับน้องเหมือนกัน คือถ้าเราใส่ await ตรงนี้ปุ๊บใช่ป่ะ ปัญหาคืออะไร เราจะต้องใส่ async ที่ฟังก์ชัน แล้วมันก็จะเป็นอย่างที่เค้าบอก ก็คือ async await async await ทีนี้เมื่อกี้ที่เค้าถามก็คือ ถ้าเราตัด await ตรงนี้ออกอะ ได้เลย ได้เลย เราทำยังไง ใช่มั้ย
โอเค เดี๋ยวคุยหลังไมค์ได้ครับ
แจกตั๋ว JetBrains และขอบคุณผู้บรรยาย25:41
พี่ครับ อยากแจกตั๋ว JetBrains มั้ย
คนนี้เค้า meaningful question มั้ย
เค้า meaningful question แบบคำถามที่ดีสร้างสรรค์ สร้างสรรค์ครับ แต่ว่าก็ยากอยู่ทั้งหมดเลย แต่ให้เป็น senior แล้วเนาะ ยังครับ ยังไม่เริ่มงานเลย ฝึกงาน อย่างถ้าเป็นผมเนี่ยก็ senior แล้วนะ คำถามยากเหลือเกินเนี่ย ผมปวดหัวอะ ได้ครับ ครับผม เดี๋ยวเชิญรับนะครับ ตั๋ว JetBrains นะครับผม
ขอขอบคุณพี่พีพีด้วยนะครับผม
เสียงปรบมือครับ