เกริ่นนำ
ฟีเจอร์ทรงพลังที่ทำให้ JavaScript ไม่เหมือนใครคือความสามารถในการทำงานแบบไม่พร้อมกันผ่านฟังก์ชันเรียกกลับ การกำหนดโค้ดเรียกกลับแบบไม่พร้อมกันช่วยให้คุณเขียนโค้ดที่ขับเคลื่อนด้วยเหตุการณ์ได้ แต่ยังช่วยให้ติดตามข้อบกพร่องด้วยเนื่องจาก JavaScript ไม่ทำงานในลักษณะเชิงเส้น
โชคดีที่ตอนนี้ใน Chrome DevTools คุณสามารถดูชุดการเรียกกลับของ JavaScript แบบอะซิงโครนัสทั้งหมด!
เมื่อเปิดใช้ฟีเจอร์การเรียกใช้สแต็กแบบไม่พร้อมกันในเครื่องมือสำหรับนักพัฒนาเว็บแล้ว คุณจะเจาะลึกสถานะของเว็บแอปได้ ณ เวลาต่างๆ เดินหน้าสแต็กเทรซเต็มรูปแบบสำหรับ Listener เหตุการณ์บางรายการ, setInterval
,setTimeout
, XMLHttpRequest
, สัญญา, requestAnimationFrame
, MutationObservers
และอื่นๆ
ระหว่างการเดินสแต็กเทรซ คุณยังวิเคราะห์ค่าของตัวแปร ณ จุดใดจุดหนึ่งของการดำเนินการรันไทม์ได้ด้วย เป็นเหมือนเครื่องย้อนเวลา สำหรับการแสดงสีหน้า
ลองมาเปิดใช้ฟีเจอร์นี้และดูสถานการณ์ตัวอย่างเหล่านี้กัน
เปิดใช้การแก้ไขข้อบกพร่องแบบไม่พร้อมกันใน Chrome
ลองใช้ฟีเจอร์ใหม่นี้โดยเปิดใช้ใน Chrome ไปที่แผงแหล่งที่มาของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome Canary
ถัดจากแผงกลุ่มการโทรทางด้านขวามือจะมีช่องทำเครื่องหมายใหม่สำหรับ "อะซิงโครนัส" สลับช่องทำเครื่องหมายเพื่อเปิดหรือปิดการแก้ไขข้อบกพร่องแบบไม่พร้อมกัน (แม้ว่าจะเปิดอยู่ คุณอาจไม่ต้องการปิด)
บันทึกเหตุการณ์ตัวจับเวลาที่ล่าช้าและการตอบสนอง XHR
ใน Gmail คุณอาจเห็นสิ่งนี้มาก่อนแล้ว
หากเกิดปัญหาในการส่งคำขอ (เซิร์ฟเวอร์มีปัญหาหรือมีปัญหาในการเชื่อมต่อเครือข่ายในฝั่งไคลเอ็นต์) Gmail จะพยายามส่งข้อความอีกครั้งโดยอัตโนมัติหลังจากหมดเวลาสั้นๆ
หากต้องการดูว่าสแต็กการเรียกใช้แบบไม่พร้อมกันช่วยเราวิเคราะห์เหตุการณ์ตัวจับเวลาที่ล่าช้าและการตอบสนอง XHR ได้อย่างไร เราจึงได้สร้างขั้นตอนนั้นขึ้นมาอีกครั้งโดยมีตัวอย่าง Gmail จำลอง ดูโค้ด JavaScript แบบเต็มได้ในลิงก์ด้านบน แต่ขั้นตอนมีดังนี้
การดูที่แผงการเรียกใช้ในเครื่องมือสำหรับนักพัฒนาเว็บเวอร์ชันก่อนหน้าเพียงอย่างเดียวแล้ว เบรกพอยท์ภายใน postOnFail()
จะทำให้คุณได้ข้อมูลเพียงเล็กน้อยว่า postOnFail()
ถูกเรียกมาจากที่ใด แต่ให้ดูข้อแตกต่างเมื่อ
เปิดสแต็กที่ไม่พร้อมกัน
เมื่อเปิดใช้สแต็กการเรียกใช้แบบไม่พร้อมกัน คุณจะดูสแต็กการเรียกใช้ทั้งหมดได้อย่างง่ายดายเพื่อดูว่าคำขอเริ่มต้นจาก submitHandler()
(ซึ่งเกิดขึ้นหลังจากที่คลิกปุ่มส่ง) หรือจาก retrySubmit()
(ซึ่งเกิดขึ้นหลังจากความล่าช้า setTimeout()
) โดยทำดังนี้
ดูนิพจน์แบบไม่พร้อมกัน
เมื่อคุณเดินหน้าการเรียกใช้ทั้งสแต็ก นิพจน์ที่ดูจะอัปเดตด้วยเพื่อแสดงถึงสถานะ ณ ขณะนั้น
ประเมินโค้ดจากขอบเขตที่ผ่านมา
นอกจากนิพจน์การดูแล้ว คุณยังโต้ตอบกับโค้ดจากขอบเขตก่อนหน้าได้ในแผงคอนโซล JavaScript ของ DevTools
ลองจินตนาการว่าคุณคือ Dr. Who และต้องการความช่วยเหลือเล็กน้อยในการเปรียบเทียบนาฬิกาก่อนที่คุณจะไปถึง Tardis กับ "ตอนนี้" คุณสามารถประเมิน จัดเก็บ และคำนวณค่าจากจุดปฏิบัติการต่างๆ ได้อย่างง่ายดายจากคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ
การใช้เครื่องมือสำหรับนักพัฒนาเว็บเพื่อจัดการกับนิพจน์จะช่วยให้คุณไม่ต้องเปลี่ยนกลับไปเป็นซอร์สโค้ด ทำการแก้ไข และรีเฟรชเบราว์เซอร์
คลี่คลายปณิธานที่สัญญาไว้แบบผูกมัด
หากคิดว่าขั้นตอนจำลองของ Gmail ก่อนหน้านี้ทำได้ยากหากไม่ได้เปิดใช้ฟีเจอร์สแต็กการเรียกใช้แบบไม่พร้อมกัน คุณนึกออกเลยว่าขั้นตอนอะซิงโครนัสที่ซับซ้อนมากขึ้น เช่น สัญญาแบบเชน จะยากขึ้นเพียงใด เรามาทบทวนตัวอย่างสุดท้ายของบทแนะนำของ Jake Archibald เกี่ยวกับพร็อพเพอร์ตี้ JavaScript กัน
นี่เป็นภาพเคลื่อนไหวสั้นๆ ของการเดินสแต็กการเรียกใช้ในตัวอย่าง async-best-example.html ของเจค
รับข้อมูลเชิงลึกเกี่ยวกับภาพเคลื่อนไหวบนเว็บของคุณ
ลองมาดูรายละเอียดเพิ่มเติมเกี่ยวกับที่เก็บถาวรของ HTML5Rocks จำภาพเคลื่อนไหวที่เร็วขึ้นด้วย requestAnimationFrame ของ Paul Lewis ได้ไหม
เปิดการสาธิต requestAnimationFrame และเพิ่มเบรกพอยท์ที่จุดเริ่มต้นของเมธอด update() (ประมาณบรรทัดที่ 874) ของ post.html การเรียกใช้สแต็กการเรียกใช้แบบไม่พร้อมกันทำให้เราได้รับข้อมูลเชิงลึกมากมายเกี่ยวกับ requestAnimationFrame รวมถึงสามารถกลับไปที่การเรียกกลับของเหตุการณ์การเลื่อนที่เริ่มต้นได้
ติดตามการอัปเดต DOM เมื่อใช้ MutationObserver
MutationObserver
ช่วยให้เราสังเกตการเปลี่ยนแปลงใน DOM ได้ ในตัวอย่างแบบง่ายนี้
เมื่อคุณคลิกปุ่ม โหนด DOM ใหม่จะถูกเพิ่มต่อท้าย <div class="rows"></div>
เพิ่มเบรกพอยท์ภายใน nodeAdded()
(บรรทัดที่ 31) ใน Demo.html เมื่อเปิดใช้สแต็กการเรียกใช้แบบไม่พร้อมกัน คุณจะย้ายสแต็กการเรียกใช้กลับไปยัง addNode()
ไปยังเหตุการณ์การคลิกเริ่มต้นได้
เคล็ดลับในการแก้ไขข้อบกพร่องของ JavaScript ในสแต็กการเรียกใช้ที่ไม่พร้อมกัน
ตั้งชื่อฟังก์ชัน
หากคุณมีแนวโน้มที่จะกำหนดโค้ดเรียกกลับทั้งหมดเป็นฟังก์ชันที่ไม่ระบุชื่อ คุณอาจตั้งชื่อแทนเพื่อให้ดูสแต็กการเรียกใช้ได้ง่ายขึ้น
ตัวอย่างเช่น ใช้ฟังก์ชันที่ไม่ระบุชื่อดังต่อไปนี้
window.addEventListener('load', function() {
// do something
});
แล้วตั้งชื่อ เช่น windowLoaded()
window.addEventListener('load', function <strong>windowLoaded</strong>(){
// do something
});
เมื่อเหตุการณ์การโหลดเริ่มทำงาน เหตุการณ์ดังกล่าวจะแสดงในสแต็กเทรซของ DevTools โดยใช้ชื่อฟังก์ชันแทน "(ฟังก์ชันที่ไม่ระบุชื่อ)" ที่ไม่ชัดเจน ซึ่งช่วยให้คุณดูสิ่งที่กำลังเกิดขึ้นในสแต็กเทรซได้ง่ายขึ้น
สำรวจเพิ่มเติม
กล่าวโดยสรุปก็คือ โค้ดเรียกกลับแบบไม่พร้อมกันทั้งหมดเหล่านี้ซึ่งเครื่องมือสำหรับนักพัฒนาเว็บจะแสดงการเรียกใช้สแต็กทั้งสาย
- ตัวจับเวลา:
เดินกลับไปยังจุดเริ่มต้นของ
setTimeout()
หรือsetInterval()
- XHR:
เดินกลับไปยังจุดที่เรียก
xhr.send()
- เฟรมภาพเคลื่อนไหว:
เดินกลับไปยังจุดที่เรียก
requestAnimationFrame
- คำมั่นสัญญา: กลับไปยังข้อกล่าวหาที่ได้รับการแก้ไขแล้ว
- Object.observe: เดินกลับไปยังบริเวณที่โค้ดเรียกกลับของผู้สังเกตการณ์ผูกไว้อยู่แต่เดิม
- MutationObservers: เดินกลับไปยังจุดที่เกิดเหตุการณ์ผู้สังเกตการณ์การเปลี่ยนแปลง
- window.postMessage(): ตรวจสอบการเรียกใช้การรับส่งข้อความภายในกระบวนการ
- DataTransferItem.getAsString()
- API ระบบไฟล์
- IndexedDB
- WebSQL
- เหตุการณ์ DOM ที่มีสิทธิ์ผ่าน
addEventListener()
: กลับไปยังตำแหน่งที่เหตุการณ์เริ่มทำงาน เหตุการณ์ DOM บางรายการไม่มีสิทธิ์ใช้ฟีเจอร์สแต็กการเรียกใช้แบบไม่พร้อมกันเนื่องจากเหตุผลด้านประสิทธิภาพ ตัวอย่างเหตุการณ์ที่มีอยู่ในปัจจุบัน ได้แก่ "scroll", "hashchange" และ "selectionchange" - เหตุการณ์มัลติมีเดียผ่าน
addEventListener()
: กลับไปยังตำแหน่งที่เหตุการณ์เริ่มทำงาน เหตุการณ์มัลติมีเดียที่ใช้ได้ ได้แก่ เหตุการณ์เสียงและวิดีโอ (เช่น "เล่น" "หยุดชั่วคราว" "เปลี่ยนอัตรา") เหตุการณ์ WebRTC MediaStreamTrackList (เช่น "addtrack", "removetrack") และเหตุการณ์ MediaSource (เช่น "sourceopen")
การสามารถดูสแต็กเทรซของโค้ดเรียกกลับ JavaScript ได้ควรจะทำให้ขนเหล่านั้นติดอยู่บนศีรษะของคุณ ฟีเจอร์นี้ในเครื่องมือสำหรับนักพัฒนาเว็บจะมีประโยชน์อย่างยิ่งเมื่อมีเหตุการณ์แบบไม่พร้อมกันหลายเหตุการณ์เกิดขึ้นโดยสัมพันธ์กัน หรือหากมีการตรวจพบข้อยกเว้นที่ตรวจไม่พบจากภายในโค้ดเรียกกลับแบบไม่พร้อมกัน
ลองใช้งานใน Chrome หากคุณมีความคิดเห็นเกี่ยวกับฟีเจอร์ใหม่นี้ โปรดแจ้งให้เราทราบเกี่ยวกับเครื่องมือติดตามข้อบกพร่องของ Chrome DevTools หรือในกลุ่มเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome