ทำความเข้าใจเกี่ยวกับซิงโครนัสและอะซิงโครนัสใน JavaScript - ส่วนที่ 2
ในส่วนแรกของโพสต์นี้เราเห็นว่า แนวคิดของซิงโครนัสและอะซิงโครนัส มีการรับรู้ ใน JavaScript. ในส่วนที่สองนี้นาย X ปรากฏขึ้นอีกครั้งเพื่อช่วยให้เราเข้าใจ วิธี setTimeout และ AJAX APIs งาน.
คำขอแปลก ๆ
ลองย้อนกลับไปยังเรื่องราวของ Mr X และภาพยนตร์ที่คุณอยากออกไป สมมติว่าคุณออกจากงานให้นาย X ก่อนออกไปข้างนอกและบอกเขาว่าเขาสามารถเริ่มงานนี้ได้เท่านั้น ห้าชั่วโมง หลังจาก เขาได้รับข้อความของคุณ.
เขาไม่มีความสุขกับมันจำไว้ว่าเขาจะไม่ส่งข้อความใหม่จนกว่าเขาจะทำกับข้อความปัจจุบันและถ้าเขารับคุณเขา ต้องรอ ห้า ชั่วโมง เพื่อเริ่มงาน ดังนั้นเพื่อไม่เป็นการเสียเวลาเขา นำมาเป็นผู้ช่วย, นายเอช.
แทนที่จะรอเขาถาม Mr H ฝากข้อความใหม่สำหรับงานในคิว หลังจากผ่านไปหลายชั่วโมงและย้ายไปยังข้อความถัดไป.
ห้าชั่วโมงที่ผ่านมา นายเอช อัพเดตคิว ด้วยข้อความใหม่ หลังจากที่เขาประมวลผลข้อความที่ได้รับทั้งหมดก่อนนายฮของคุณนายเอ็กซ์ ดำเนินงานตามที่คุณร้องขอ. ดังนั้นวิธีนี้คุณสามารถปล่อยให้เป็น ปฏิบัติตามในภายหลัง, และไม่ต้องรอจนกว่าจะสำเร็จ.
แต่ทำไมนาย H ฝากข้อความไว้ในคิวแทนที่จะติดต่อคุณ X โดยตรง เพราะอย่างที่ฉันได้กล่าวไปในตอนแรก เท่านั้น วิธีที่จะติดต่อนาย X คือ โดยฝากข้อความถึงเขา ผ่านโทรศัพท์ - ไม่มีข้อยกเว้น.
1. setTimeout ()
วิธี
สมมติว่าคุณมีชุดรหัสที่คุณต้องการ ดำเนินการหลังจากเวลาที่แน่นอน. เพื่อที่จะทำเช่นนั้นคุณเพียงแค่ ห่อไว้ในฟังก์ชั่น, และ เพิ่มลงใน setTimeout ()
วิธี พร้อมกับเวลาล่าช้า ไวยากรณ์ของ setTimeout ()
มีดังนี้:
setTimeout (ฟังก์ชั่น, หน่วงเวลา, หาเรื่อง ... )
หาเรื่อง ...
พารามิเตอร์ย่อมาจากอาร์กิวเมนต์ใด ๆ ที่ฟังก์ชันใช้และ เวลาล่าช้า
จะถูกเพิ่มในหน่วยมิลลิวินาที ด้านล่างคุณสามารถดูตัวอย่างโค้ดแบบง่าย ๆ “เฮ้” ในคอนโซลหลังจาก 3 วินาที.
setTimeout (function () console.log ('hey'), 3000);
ครั้งหนึ่ง setTimeout ()
เริ่มทำงาน, แทนการบล็อคการโทรซ้อน จนกว่าเวลาหน่วงที่ระบุจะสิ้นสุดลง a ตัวจับเวลาถูกทริกเกอร์, และ call stack จะถูกทำให้ว่างเปล่าสำหรับข้อความถัดไป (คล้ายกับการติดต่อระหว่าง Mr X และ Mr H).
เมื่อหมดเวลาข้อความใหม่ เข้าร่วมคิว, และวงเหตุการณ์หยิบมันขึ้นมาเมื่อโทรสแต็คเป็นอิสระหลังจากการประมวลผลข้อความทั้งหมดก่อนที่มัน - ดังนั้นรหัสที่ทำงานแบบอะซิงโครนัส.

2. AJAX
AJAX (Asynchronous JavaScript และ XML) เป็นแนวคิดที่ใช้ XMLHttpRequest
(XHR) API เป็น ทำการร้องขอเซิร์ฟเวอร์ และ จัดการกับการตอบสนอง.
เมื่อเบราว์เซอร์ทำการร้องขอเซิร์ฟเวอร์โดยไม่ใช้ XMLHttpRequest รีเฟรชหน้า และ โหลด UI อีกครั้ง. เมื่อประมวลผลคำขอและการตอบสนองถูกจัดการโดย XHR API และ UI ยังคงไม่ได้รับผลกระทบ.

ดังนั้นโดยทั่วไปเป้าหมายคือ ทำการร้องขอโดยไม่มีการโหลดหน้าซ้ำ. ตอนนี้อยู่ที่ไหน “ไม่ตรงกัน” ในเรื่องนี้? เพียงแค่ใช้รหัส XHR (ซึ่งเราจะเห็นในอีกสักครู่) ไม่ได้หมายความว่ามันเป็น AJAX เพราะ XHR API สามารถ ทำงานได้ทั้งในแบบซิงโครนัสและแบบอะซิงโครนัส.
XHR โดยค่าเริ่มต้น ถูกตั้งค่าเป็น ทำงานแบบอะซิงโครนัส; เมื่อฟังก์ชั่นทำการร้องขอโดยใช้ XHR มัน ผลตอบแทนโดยไม่รอการตอบสนอง.
หาก XHR ได้รับการกำหนดค่าให้ ซิงโครนัส, จากนั้นฟังก์ชั่นจะรอจนกระทั่ง ได้รับการตอบสนองและประมวลผลแล้ว ก่อนกลับมา.
ตัวอย่างรหัส 1
ตัวอย่างนี้นำเสนอ XMLHttpRequest
การสร้างวัตถุ. เปิด()
วิธีการตรวจสอบความถูกต้องของคำขอ URL และ ส่ง()
วิธีการส่งคำขอ.
var xhr = XMLHttpRequest ใหม่ (); xhr.open ("GET", url); xhr.send ();
การเข้าถึงข้อมูลการตอบสนองโดยตรงหลังจากใด ๆ ส่ง()
จะไร้ประโยชน์เพราะ ส่ง()
ไม่รอ จนกว่าคำขอจะเสร็จสมบูรณ์ โปรดจำไว้ว่า XMLHTTPRequest ถูกตั้งค่าให้ทำงานแบบอะซิงโครนัสตามค่าเริ่มต้น.
ตัวอย่างรหัส 2
hello.txt
ไฟล์ในตัวอย่างนี้เป็นไฟล์ข้อความแบบง่ายที่มีข้อความ 'hello' คำตอบ
คุณสมบัติของ XHR ไม่ถูกต้องเนื่องจากไม่ได้ส่งข้อความ 'hello'.
var xhr = XMLHttpRequest ใหม่ (); xhr.open ("GET", "hello.txt"); xhr.send (); document.write (xhr.response); // สตริงว่าง
XHR ใช้ไมโครรูทีนนั้น ตรวจสอบการตอบสนองต่อไป ในทุกมิลลิวินาทีและ ก่อให้เกิดเหตุการณ์ฟรี สำหรับรัฐต่าง ๆ คำขอผ่าน เมื่อโหลดคำตอบแล้ว, เหตุการณ์โหลดจะถูกเรียกใช้โดย XHR, ซึ่งสามารถส่งมอบการตอบสนองที่ถูกต้อง.
var xhr = XMLHttpRequest ใหม่ (); xhr.open ("GET", "hello.txt"); xhr.send (); xhr.onload = function () document.write (this.response) // เขียน 'hello' ลงในเอกสาร
การตอบสนองภายในเหตุการณ์โหลด เอาท์พุท 'สวัสดี', ข้อความที่ถูกต้อง.
การเลือกใช้วิธีอะซิงโครนัสเป็นสิ่งที่ต้องการเนื่องจากจะไม่ปิดกั้นสคริปต์อื่นจนกว่าคำขอจะเสร็จสมบูรณ์.
หากการตอบสนองจะต้องมีการประมวลผลพร้อมกันเราจะผ่าน เท็จ
เป็นอาร์กิวเมนต์สุดท้ายของ เปิด
, ที่ ตั้งค่าสถานะ XHR API พูดมัน จะต้องมีการซิงโครนัส (โดยค่าเริ่มต้นอาร์กิวเมนต์สุดท้ายของ เปิด
คือ จริง
, ซึ่งคุณไม่จำเป็นต้องระบุอย่างชัดเจน).
var xhr = XMLHttpRequest ใหม่ (); xhr.open ("GET", "hello.txt", เท็จ); xhr.send (); document.write (xhr.response); // เขียน 'hello' ลงในเอกสาร
เรียนรู้ทั้งหมดนี้ทำไม?
ผู้เริ่มต้นเกือบทั้งหมดทำผิดพลาดด้วยแนวคิดอะซิงโครนัสเช่น setTimeout ()
และ AJAX เช่นโดยสมมติว่า setTimeout ()
รันรหัสหลังจากเวลาล่าช้าหรือโดยการประมวลผลการตอบสนองโดยตรงภายในฟังก์ชั่นการร้องขอ AJAX.
หากคุณรู้ว่าตัวต่อปริศนาเหมาะสมกับคุณได้ หลีกเลี่ยงความสับสนเช่นนั้น. คุณรู้ว่าเวลาหน่วงใน setTimeout ()
ไม่ได้ระบุเวลา เมื่อการประมวลผลรหัสเริ่มต้น, แต่เวลา เมื่อหมดเวลา และข้อความใหม่จะเข้าคิวซึ่งจะถูกประมวลผลเฉพาะเมื่อ call stack มีอิสระในการทำเช่นนั้น.