ดูเหมือนว่าทุกคนส่วนใหญ่จะส่งคำขอแบบอะซิงโครนัสกับ XMLHttpRequest แต่เห็นได้ชัดว่ามีความสามารถในการร้องขอแบบซิงโครนัสบ่งชี้ว่าอาจมีเหตุผลที่ถูกต้องในการทำเช่นนั้น แล้วเหตุผลที่ถูกต้องนั่นคืออะไร?
ดูเหมือนว่าทุกคนส่วนใหญ่จะส่งคำขอแบบอะซิงโครนัสกับ XMLHttpRequest แต่เห็นได้ชัดว่ามีความสามารถในการร้องขอแบบซิงโครนัสบ่งชี้ว่าอาจมีเหตุผลที่ถูกต้องในการทำเช่นนั้น แล้วเหตุผลที่ถูกต้องนั่นคืออะไร?
คำตอบ:
ฉันคิดว่าอาจเป็นที่นิยมมากขึ้นเมื่อมาตรฐาน HTML 5 ก้าวหน้าขึ้น หากเว็บแอปพลิเคชันสามารถเข้าถึงผู้ปฏิบัติงานบนเว็บได้ฉันสามารถคาดการณ์ล่วงหน้าว่านักพัฒนาโดยใช้ผู้ปฏิบัติงานบนเว็บโดยเฉพาะเพื่อส่งคำขอแบบซิงโครนัสตามที่โจนาธานกล่าวเพื่อให้แน่ใจว่ามีคำขอหนึ่งรายการเกิดขึ้นก่อนหน้าอื่น ด้วยสถานการณ์ปัจจุบันของเธรดเดียวจึงเป็นการออกแบบที่น้อยกว่าในอุดมคติเนื่องจากบล็อกจนกว่าคำขอจะเสร็จสมบูรณ์
XHR แบบซิงโครนัสมีประโยชน์สำหรับการบันทึกข้อมูลผู้ใช้ หากคุณจัดการbeforeunload
เหตุการณ์คุณสามารถอัปโหลดข้อมูลไปยังเซิร์ฟเวอร์ได้ในขณะที่ผู้ใช้ปิดเพจ
หากทำได้โดยใช้ตัวเลือก async หน้าสามารถปิดได้ก่อนที่คำขอจะเสร็จสมบูรณ์ การทำพร้อมกันนี้ช่วยให้มั่นใจได้ว่าคำขอจะเสร็จสมบูรณ์หรือล้มเหลวในลักษณะที่คาดไว้
คำใบ้ด้านล่าง - แต่ไม่ประสบความสำเร็จในการส่ง - เนื่องจากการมาของการจัดการคำขอแบบอะซิงโครนัสที่ดีขึ้นจึงไม่มีเหตุผลที่จะใช้คำขอแบบซิงโครนัสเว้นแต่จะตั้งใจบล็อกผู้ใช้ไม่ให้ทำอะไรจนกว่าคำขอจะเสร็จสมบูรณ์ - ฟังดูเป็นอันตราย: )
แม้ว่าสิ่งนี้อาจฟังดูไม่ดี แต่อาจมีบางครั้งที่สำคัญที่คำขอ (หรือชุดคำขอ) เกิดขึ้นก่อนที่ผู้ใช้จะออกจากหน้าหรือก่อนที่จะดำเนินการ - บล็อกการเรียกใช้รหัสอื่น ๆ (เช่นการป้องกันปุ่มย้อนกลับ) อาจ อาจลดข้อผิดพลาด / การบำรุงรักษาสำหรับระบบที่ออกแบบมาไม่ดี ที่กล่าวว่าฉันไม่เคยเห็นมันในป่าและเน้นว่าควรหลีกเลี่ยง
ไลบรารีเช่นเดียวกับสัญญาแสร้งทำเป็นซิงโครไนซ์โดยการผูกมัดกระบวนการผ่านการเรียกกลับ สิ่งนี้เหมาะกับความต้องการในการพัฒนาส่วนใหญ่ซึ่งความต้องการคือการสั่งซื้อเหตุการณ์ที่ไม่ปิดกั้นซึ่งทำให้เบราว์เซอร์สามารถรักษาการตอบสนองของผู้ใช้ได้ (UX ที่ดี)
ตามที่ระบุไว้ในเอกสาร Mozillaมีหลายกรณีที่คุณต้องใช้คำขอแบบซิงโครนัส อย่างไรก็ตามรายการนี้ยังเป็นวิธีแก้ปัญหาที่ใช้บีคอน (ไม่มีใน IE / Safari) สำหรับกรณีดังกล่าว แม้ว่าจะเป็นการทดลอง แต่หากได้รับการยอมรับตามมาตรฐานก็สามารถใส่ตะปูลงในโลงศพแบบซิงโครนัสได้
คุณต้องการทำการโทรแบบซิงโครนัสในการประมวลผลแบบธุรกรรมใด ๆ หรือที่ใดก็ตามที่จำเป็นต้องมีลำดับการทำงาน
ตัวอย่างเช่นสมมติว่าคุณต้องการปรับแต่งเหตุการณ์เพื่อออกจากระบบหลังจากเล่นเพลง หากการดำเนินการออกจากระบบเกิดขึ้นก่อนเพลงจะไม่เล่น สิ่งนี้ต้องมีการซิงโครไนซ์คำขอ
อีกเหตุผลหนึ่งก็คือเมื่อทำงานกับ WebService โดยเฉพาะอย่างยิ่งเมื่อทำการคำนวณบนเซิร์ฟเวอร์
ตัวอย่าง:เซิร์ฟเวอร์มีตัวแปรที่มีค่า 1
Step (1) Perform Update: add 1 to variable Step (2) Perform Update: set variable to the power of 3 End Value: variable equals 8
ถ้าขั้นที่ (2) เกิดขึ้นก่อนค่าสุดท้ายคือ 2 ไม่ใช่ 8 ดังนั้นจึงจำเป็นต้องมีลำดับการดำเนินการและการซิงโครไนซ์
มีไม่กี่ครั้งที่การโทรแบบซิงโครนัสอาจถูกต้องตามตัวอย่างในโลกแห่งความจริงทั่วไป บางทีเมื่อคลิกเข้าสู่ระบบแล้วคลิกส่วนหนึ่งของไซต์ที่ต้องการให้ผู้ใช้เข้าสู่ระบบ
ดังที่คนอื่น ๆ กล่าวไว้ว่ามันจะผูกเบราว์เซอร์ของคุณดังนั้นอย่าอยู่ห่างจากที่คุณทำได้
อย่างไรก็ตามแทนที่จะเป็นการโทรแบบซิงโครนัสผู้ใช้มักต้องการหยุดเหตุการณ์ที่กำลังโหลดอยู่แล้วดำเนินการอื่น ๆ ในลักษณะนี้คือการซิงโครไนซ์เนื่องจากเหตุการณ์แรกจะหยุดก่อนที่เหตุการณ์ที่สองจะเริ่มขึ้น ในการดำเนินการนี้ให้ใช้วิธี abort () บนอ็อบเจ็กต์การเชื่อมต่อ xml
ฉันจะบอกว่าหากคุณพิจารณาบล็อกเบราว์เซอร์ของผู้ใช้ในขณะที่คำขอเสร็จสมบูรณ์แล้วให้ใช้คำขอแบบซิงโครนัส
หากการทำให้เป็นอนุกรมของคำขอเป็นเป้าหมายของคุณคุณสามารถทำได้โดยใช้คำขอ async โดยให้การเรียกกลับ onComplete ของคำขอก่อนหน้าของคุณเริ่มต้นในบรรทัดถัดไป
มีหลายกรณีในโลกแห่งความเป็นจริงที่การบล็อก UI เป็นพฤติกรรมที่ต้องการ
ใช้แอพที่มีหลายฟิลด์และบางฟิลด์ต้องได้รับการตรวจสอบความถูกต้องโดยการเรียก xmlhttp ไปยังเซิร์ฟเวอร์ระยะไกลที่ให้เป็นอินพุตค่าของฟิลด์นี้และค่าฟิลด์อื่น ๆ
ในโหมดซิงโครนัสตรรกะนั้นง่ายการบล็อกที่ผู้ใช้พบนั้นสั้นมากและไม่มีปัญหา
ในโหมด async ผู้ใช้อาจเปลี่ยนค่าของฟิลด์อื่น ๆ ในขณะที่กำลังตรวจสอบค่าเริ่มต้น การเปลี่ยนแปลงเหล่านี้จะทริกเกอร์การเรียก xmlhttp อื่นด้วยค่าจากฟิลด์เริ่มต้นที่ยังไม่ได้รับการตรวจสอบ จะเกิดอะไรขึ้นหากการตรวจสอบความถูกต้องเบื้องต้นล้มเหลว ระเบียบบริสุทธิ์ หากโหมดซิงค์เลิกใช้งานและไม่ได้รับอนุญาตตรรกะของแอปพลิเคชันจะกลายเป็นฝันร้ายที่ต้องจัดการ โดยทั่วไปจะต้องเขียนแอปพลิเคชันใหม่เพื่อจัดการการล็อก (เช่นปิดใช้งานรายการอื่น ๆ ในระหว่างกระบวนการตรวจสอบความถูกต้อง) ความซับซ้อนของโค้ดเพิ่มขึ้นอย่างมาก หากไม่ทำเช่นนั้นอาจนำไปสู่ความล้มเหลวของตรรกะและข้อมูลเสียหายในที่สุด
โดยทั่วไปคำถามคืออะไรคือประสบการณ์ UI ที่ไม่ถูกบล็อกหรือความเสี่ยงต่อการเสียหายของข้อมูล คำตอบควรอยู่กับผู้พัฒนาแอปพลิเคชันไม่ใช่ W3C
ฉันสามารถเห็นการใช้สำหรับการร้องขอ XHR แบบซิงโครนัสที่จะใช้เมื่อทรัพยากรในตำแหน่งตัวแปรต้องโหลดก่อนทรัพยากรแบบคงที่อื่น ๆ ในหน้าที่ขึ้นอยู่กับทรัพยากรแรกที่จะทำงานได้อย่างสมบูรณ์ ในความเป็นจริงฉันกำลังใช้คำขอ XHR ดังกล่าวในโครงการย่อยเล็ก ๆ ของฉันเองในขณะที่ทรัพยากร JavaScript อยู่ในตำแหน่งตัวแปรบนเซิร์ฟเวอร์โดยขึ้นอยู่กับชุดของพารามิเตอร์เฉพาะ ทรัพยากร JavaScript ที่ตามมาต้องอาศัยทรัพยากรตัวแปรเหล่านั้นและไฟล์ดังกล่าวต้องได้รับการรับรองว่าจะโหลดก่อนที่ไฟล์อื่น ๆ ที่เชื่อถือได้จะถูกโหลดจึงทำให้แอปพลิเคชันทั้งหมด
รากฐานความคิดนั้นขยายออกไปจากคำตอบของ vol7ron ขั้นตอนการทำธุรกรรมเป็นช่วงเวลาเดียวที่ควรทำคำขอแบบซิงโครนัส ในกรณีอื่น ๆ ส่วนใหญ่การโทรแบบอะซิงโครนัสเป็นทางเลือกที่ดีกว่าซึ่งหลังจากการโทร DOM จะได้รับการอัปเดตตามความจำเป็น ในหลาย ๆ กรณีเช่นระบบที่ใช้ผู้ใช้คุณอาจมีคุณลักษณะบางอย่างที่ล็อกไว้สำหรับ "ผู้ใช้ที่ไม่ได้รับอนุญาต" จนกว่าจะมีการลงชื่อเข้าใช้คุณลักษณะเหล่านี้หลังจากการโทรแบบอะซิงโครนัสจะถูกปลดล็อกผ่านขั้นตอนการอัปเดต DOM
ในที่สุดฉันก็ต้องบอกว่าฉันเห็นด้วยกับประเด็นของบุคคลส่วนใหญ่ในเรื่องนี้: ทุกที่ที่เป็นไปได้ควรหลีกเลี่ยงคำขอ XHR แบบซิงโครนัสเนื่องจากวิธีการทำงานเบราว์เซอร์จะล็อกด้วยการโทรแบบซิงโครนัส เมื่อใช้คำขอซิงโครนัสควรทำในลักษณะที่ปกติเบราว์เซอร์จะถูกล็อกอย่างไรก็ตามในหัวข้อ HEAD ก่อนที่การโหลดหน้าเว็บจะเกิดขึ้นจริง
ในปี 2015 แอป JavaScript บนเดสก์ท็อปกำลังเป็นที่นิยมมากขึ้น โดยปกติแล้วในแอพเหล่านั้นเมื่อโหลดไฟล์ในเครื่อง (และโหลดโดยใช้ XHR เป็นตัวเลือกที่ใช้ได้อย่างสมบูรณ์แบบ) ความเร็วในการโหลดนั้นเร็วมากจนมีจุดที่ซับซ้อนเกินไปเล็กน้อยที่จะทำให้โค้ดทับซ้อนกับ async แน่นอนว่าอาจมีบางกรณีที่ async เป็นวิธีที่จะไป (ขอเนื้อหาจากอินเทอร์เน็ตโหลดไฟล์ขนาดใหญ่จริงๆหรือไฟล์จำนวนมากในชุดเดียว) แต่มิฉะนั้นการซิงค์จะทำงานได้ดี (และใช้งานง่ายกว่ามาก) .
jQuery ใช้ AJAX แบบซิงโครนัสภายในภายใต้สถานการณ์บางอย่าง เมื่อแทรก HTML ที่มีสคริปต์เบราว์เซอร์จะไม่เรียกใช้งาน ต้องดำเนินการสคริปต์ด้วยตนเอง สคริปต์เหล่านี้อาจแนบตัวจัดการคลิก สมมติว่าผู้ใช้คลิกที่องค์ประกอบก่อนที่จะแนบตัวจัดการและหน้าจะไม่ทำงานตามที่ตั้งใจไว้ ดังนั้นเพื่อป้องกันสภาวะการแข่งขันจะใช้ AJAX แบบซิงโครนัสเพื่อดึงสคริปต์เหล่านั้น เนื่องจาก AJAX แบบซิงโครนัสบล็อกทุกอย่างได้อย่างมีประสิทธิภาพจึงมั่นใจได้ว่าสคริปต์และเหตุการณ์จะดำเนินการตามลำดับที่ถูกต้อง
เหตุผล:
สมมติว่าคุณมีแอปพลิเคชัน ajax ที่ต้องทำ http ครึ่งโหลเพื่อโหลดข้อมูลต่างๆจากเซิร์ฟเวอร์ก่อนที่ผู้ใช้จะสามารถโต้ตอบใด ๆ ได้
เห็นได้ชัดว่าคุณต้องการให้สิ่งนี้ถูกกระตุ้นจาก onload
การโทรแบบซิงโครนัสทำงานได้ดีมากสำหรับสิ่งนี้โดยไม่ต้องเพิ่มความซับซ้อนให้กับโค้ด มันง่ายและตรงไปตรงมา
ข้อเสียเปรียบ:
ข้อเสียเปรียบเพียงประการเดียวคือเบราว์เซอร์ของคุณจะล็อกจนกว่าข้อมูลทั้งหมดจะโหลดหรือหมดเวลา สำหรับแอปพลิเคชัน ajax ที่เป็นปัญหานี่ไม่ใช่ปัญหามากนักเนื่องจากแอปพลิเคชันไม่มีประโยชน์จนกว่าจะโหลดข้อมูลเริ่มต้นทั้งหมด
ทางเลือก?
อย่างไรก็ตามเบราว์เซอร์จำนวนมากล็อคหน้าต่าง / แท็บทั้งหมดเมื่อในขณะที่จาวาสคริปต์ไม่ว่างในหนึ่งในนั้นซึ่งเป็นปัญหาการออกแบบเบราว์เซอร์ที่โง่เขลา - แต่ผลที่ตามมาการบล็อกบนเครือข่ายที่ช้าอาจจะไม่สุภาพหากป้องกันไม่ให้ผู้ใช้ใช้แท็บอื่น ในขณะที่รอให้หน้า ajax โหลด
อย่างไรก็ตามดูเหมือนว่าการรับซิงโครนัสจะถูกลบหรือ จำกัด จากเบราว์เซอร์ล่าสุดอยู่ดี ฉันไม่แน่ใจว่าเป็นเพราะใครบางคนตัดสินใจว่าพวกเขาแย่เสมอไปหรือถ้าผู้เขียนเบราว์เซอร์สับสนกับ WC Working Draft ในหัวข้อนี้
http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open- วิธีการทำให้ดูเหมือน (ดูหัวข้อ 4.7.3) คุณไม่ได้รับอนุญาตให้ตั้งค่าการหมดเวลาเมื่อใช้โหมดบล็อก . ดูเหมือนว่าจะใช้งานง่ายสำหรับฉัน: เมื่อใดก็ตามที่มีการบล็อก IO การตั้งค่าระยะหมดเวลาที่เหมาะสมอย่างสุภาพดังนั้นเหตุใดจึงอนุญาตให้บล็อก io แต่ไม่ใช้ระยะหมดเวลาที่ระบุ
ความเห็นของฉันคือการบล็อก IO มีบทบาทสำคัญในบางสถานการณ์ แต่ต้องดำเนินการอย่างถูกต้อง แม้ว่าแท็บเบราว์เซอร์หรือหน้าต่างหนึ่งจะไม่สามารถล็อคแท็บหรือหน้าต่างอื่น ๆ ทั้งหมดได้ แต่นั่นก็เป็นข้อบกพร่องในการออกแบบเบราว์เซอร์ ความอัปยศที่เกิดจากความอัปยศ แต่เป็นที่ยอมรับอย่างสมบูรณ์ในบางกรณีที่แท็บหรือหน้าต่างแต่ละรายการจะไม่ตอบสนองเป็นเวลาสองถึงสามวินาที (เช่นการใช้การบล็อก IO / HTTP GET) ในบางสถานการณ์ - ตัวอย่างเช่นในการโหลดหน้าเว็บอาจมีข้อมูลจำนวนมาก จำเป็นต้องมีก่อนที่จะทำอะไรต่อไป บางครั้งการใช้รหัสบล็อกอย่างถูกต้องเป็นวิธีที่สะอาดที่สุด
แน่นอนว่าฟังก์ชันเทียบเท่าในกรณีนี้สามารถรับได้โดยใช้ http แบบอะซิงโครนัส แต่ต้องมีรูทีนโง่ ๆ แบบไหน
ฉันเดาว่าฉันจะลองทำอะไรตามบรรทัดเหล่านี้:
ในการโหลดเอกสารให้ดำเนินการดังต่อไปนี้: 1: ตั้งค่าตัวแปรแฟล็ก "เสร็จสิ้น" ส่วนกลาง 6 ตัวแปรเริ่มต้นเป็น 0 2: ดำเนินการรับพื้นหลังทั้ง 6 รายการ (สมมติว่าลำดับไม่สำคัญ)
จากนั้นการเรียกกลับที่สมบูรณ์สำหรับ http ทั้ง 6 รายการจะตั้งค่าแฟล็ก "เสร็จสิ้น" ตามลำดับ นอกจากนี้การโทรกลับแต่ละครั้งจะตรวจสอบแฟล็กอื่น ๆ ทั้งหมดเพื่อดูว่า HTTP ทั้ง 6 ได้รับเสร็จสมบูรณ์หรือไม่ การโทรกลับครั้งสุดท้ายที่จะทำให้เสร็จสมบูรณ์เมื่อเห็นว่าคนอื่น ๆ ทำเสร็จแล้วจะเรียกใช้ฟังก์ชันเริ่มต้นจริงซึ่งจะตั้งค่าทุกอย่างตอนนี้ข้อมูลทั้งหมดถูกดึงมา
หากลำดับของการดึงข้อมูลมีความสำคัญ - หรือหากเว็บเซิร์ฟเวอร์ไม่สามารถรับคำขอหลายรายการในเวลาเดียวกันคุณจะต้องมีสิ่งต่อไปนี้:
ใน onload () http get แรกจะเปิดตัว ในการเรียกกลับครั้งที่สองจะเปิดตัว ในการโทรกลับครั้งที่สามและอื่น ๆ โดยการโทรกลับแต่ละครั้งจะเรียกใช้ HTTP GET ถัดไป เมื่อคนสุดท้ายกลับมามันจะเรียกรูทีนจริง init ()
จะเกิดอะไรขึ้นถ้าคุณโทรแบบซิงโครนัสในรหัสการผลิต
ท้องฟ้าถล่มลงมา
ไม่จริงจังผู้ใช้ไม่ชอบเบราว์เซอร์ที่ถูกล็อก
ฉันใช้มันเพื่อตรวจสอบชื่อผู้ใช้ในระหว่างการตรวจสอบว่าไม่มีชื่อผู้ใช้อยู่แล้ว
ฉันรู้ว่ามันจะดีกว่าถ้าทำแบบอะซิงโครนัส แต่ฉันควรใช้รหัสอื่นสำหรับกฎการตรวจสอบนี้โดยเฉพาะ ผมอธิบายดีกว่า การตั้งค่าการตรวจสอบความถูกต้องของฉันใช้ฟังก์ชันการตรวจสอบความถูกต้องบางอย่างซึ่งส่งคืนจริงหรือเท็จขึ้นอยู่กับว่าข้อมูลนั้นถูกต้อง
เนื่องจากฟังก์ชันต้องส่งคืนฉันจึงไม่สามารถใช้เทคนิคอะซิงโครนัสได้ดังนั้นฉันจึงทำซิงโครนัสนั้นและหวังว่าเซิร์ฟเวอร์จะตอบทันทีเพียงพอที่จะไม่ให้เห็นได้ชัดเจน หากฉันใช้การเรียกกลับ AJAX ฉันจะต้องจัดการกับการดำเนินการที่เหลือแตกต่างจากวิธีการตรวจสอบความถูกต้องอื่น ๆ
false
) และตั้งค่าเป็นจริงหรือเท็จเมื่อเซิร์ฟเวอร์ตอบสนอง ในการเปลี่ยนแปลงของฟิลด์คุณรีเซ็ตแฟล็กและเรียกเซิร์ฟเวอร์อีกครั้ง
บางครั้งคุณมีการกระทำที่ขึ้นอยู่กับคนอื่น ตัวอย่างเช่นการดำเนินการ B สามารถเริ่มต้นได้ก็ต่อเมื่อ A เสร็จสิ้นเท่านั้น วิธีการซิงโครมักจะใช้เพื่อหลีกเลี่ยงสภาพการแข่งขัน บางครั้งการใช้การโทรแบบซิงโครนัสเป็นการใช้งานที่ง่ายกว่าจากนั้นจึงสร้างตรรกะที่ซับซ้อนเพื่อตรวจสอบสถานะของการโทรแบบอะซิงโครนัสทุกครั้งที่ขึ้นอยู่กับกันและกัน
ปัญหาในแนวทางนี้คือคุณ "บล็อก" เบราว์เซอร์ของผู้ใช้จนกว่าการดำเนินการจะเสร็จสิ้น (จนกว่าคำขอจะส่งคืนเสร็จสิ้นโหลด ฯลฯ ) ดังนั้นควรระมัดระวังในการใช้งาน
ฉันใช้การโทรแบบซิงโครนัสเมื่อพัฒนาโค้ด - สิ่งที่คุณทำในขณะที่คำขอกำลังเดินทางไปและกลับจากเซิร์ฟเวอร์สามารถปิดบังสาเหตุของข้อผิดพลาดได้
เมื่อมันใช้งานได้ฉันจะทำให้เป็นแบบอะซิงโครนัส แต่ฉันพยายามรวมตัวจับเวลาการยกเลิกและการเรียกกลับล้มเหลวเพราะคุณไม่มีทางรู้ ...
SYNC vs ASYNC: อะไรคือความแตกต่าง?
โดยทั่วไปแล้วจะเดือดลงถึงสิ่งนี้:
console.info('Hello, World!');
doSomething(function handleResult(result) {
console.info('Got result!');
});
console.info('Goodbye cruel world!');
เมื่อdoSomething
ใดที่ซิงโครนัสสิ่งนี้จะพิมพ์:
Hello, World!
Got result!
Goodbye cruel world!
ในทางตรงกันข้ามหากdoSomething
เป็นแบบอะซิงโครนัสสิ่งนี้จะพิมพ์:
Hello, World!
Goodbye cruel world!
Got result!
เนื่องจากฟังก์ชันdoSomething
กำลังทำงานแบบอะซิงโครนัสฟังก์ชันจึงส่งกลับก่อนที่จะทำงานเสร็จ ดังนั้นเราจะได้ผลลัพธ์หลังจากการพิมพ์เท่านั้นGoodbye cruel world!
หากเราขึ้นอยู่กับผลลัพธ์ของการโทรแบบไม่ซิงค์เราจำเป็นต้องวางรหัสที่ขึ้นอยู่กับการโทรกลับ:
console.info('Hello, World!');
doSomething(function handleResult(result) {
console.info('Got result!');
if (result === 'good') {
console.info('I feel great!');
}
else {
console.info('Goodbye cruel world!');
}
});
ด้วยเหตุนี้ความจริงที่ว่า 2 หรือสามสิ่งต้องเกิดขึ้นตามลำดับจึงไม่มีเหตุผลที่จะทำพร้อมกัน (แม้ว่ารหัสการซิงค์จะง่ายกว่าสำหรับคนส่วนใหญ่ที่จะทำงานด้วย)
ทำไมต้องใช้ XMLHTTPREQUEST แบบซิงโครนัส
มีบางสถานการณ์ที่คุณต้องการผลลัพธ์ก่อนที่ฟังก์ชันที่เรียกจะเสร็จสมบูรณ์ พิจารณาสถานการณ์นี้:
function lives(name) {
return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');
สมมติว่าเราไม่สามารถควบคุมรหัสการโทร ( console.info
สาย) และจำเป็นต้องเปลี่ยนฟังก์ชั่นlives
เพื่อถามเซิร์ฟเวอร์ ... ไม่มีทางที่เราจะร้องขอ async ไปยังเซิร์ฟเวอร์จากภายในได้lives
และยังคงได้รับคำตอบก่อนที่จะlives
เสร็จสมบูรณ์ ดังนั้นเราจะไม่ทราบว่าจะกลับหรือtrue
false
วิธีเดียวที่จะได้ผลลัพธ์ก่อนที่ฟังก์ชันจะเสร็จสมบูรณ์คือการร้องขอแบบซิงโครนัส
ตามที่Sami Samhuri
กล่าวไว้ในคำตอบของเขาสถานการณ์จริงที่คุณอาจต้องการคำตอบสำหรับคำขอเซิร์ฟเวอร์ของคุณก่อนที่ฟังก์ชันของคุณจะยุติคือonbeforeunload
เหตุการณ์เนื่องจากเป็นฟังก์ชันสุดท้ายจากแอปของคุณที่จะทำงานก่อนที่หน้าต่างจะถูกปิด
ฉันไม่จำเป็นต้องโทรซิงค์ แต่ฉันใช้พวกเขาทุกที่ที่พวกเขาง่ายกว่า
กรุณาอย่า การโทรแบบซิงโครนัสจะล็อกเบราว์เซอร์ของคุณและทำให้แอปไม่ตอบสนอง แต่คุณพูดถูก รหัส Async ยากกว่า อย่างไรก็ตามมีวิธีที่จะทำให้จัดการกับมันได้ง่ายขึ้นมาก ไม่ง่ายเหมือนการซิงค์รหัส แต่มันกำลังใกล้เข้ามา: Promise s
นี่คือตัวอย่าง: การเรียกแบบ asynch สองครั้งควรดำเนินการให้สำเร็จก่อนที่โค้ดส่วนที่สามจะทำงาน:
var carRented = rentCar().then(function(car){
gasStation.refuel(car);
});
var hotelBooked = bookHotel().then(function(reservation) {
reservation.confirm();
});
Promise.all([carRented, hotelBooked]).then(function(){
// At this point our car is rented and our hotel booked.
goOnHoliday();
});
นี่คือวิธีที่คุณจะนำไปใช้bookHotel
:
function bookHotel() {
return new Promise(function(resolve, reject){
if (roomsAvailable()) {
var reservation = reserveRoom();
resolve(reservation);
}
else {
reject(new Error('Could not book a reservation. No rooms available.'));
}
});
}
ดูเพิ่มเติม: เขียนดีกว่า JavaScript กับสัญญา
XMLHttpRequest
โดยปกติจะใช้สำหรับคำขอแบบอะซิงโครนัส บางครั้ง (สำหรับการดีบักหรือตรรกะทางธุรกิจที่เฉพาะเจาะจง) คุณต้องการเปลี่ยนการเรียก async ทั้งหมด / หลายรายการในหน้าเดียวเพื่อซิงค์
คุณต้องการที่จะทำโดยไม่ต้องเปลี่ยนทุกอย่างในรหัส JS ของคุณ แฟล็ก async / sync ทำให้คุณมีความสามารถดังกล่าวและหากได้รับการออกแบบอย่างถูกต้องคุณต้องเปลี่ยนเพียงบรรทัดเดียวในรหัสของคุณ / เปลี่ยนค่าหนึ่งvar
ในระหว่างเวลาดำเนินการ
Firefox (และเป็นไปได้ว่าเบราว์เซอร์ที่ไม่ใช่ IE ทั้งหมด) ไม่รองรับ async XHR timeOut
HTML5 WebWorkersรองรับการหมดเวลา ดังนั้นคุณอาจต้องการตัดการร้องขอ XHR การซิงค์ไปยัง WebWorker ด้วยการหมดเวลาเพื่อใช้งาน XHR แบบ async ที่มีลักษณะการหมดเวลา
ฉันเพิ่งมีสถานการณ์ที่คำขอแบบอะซิงโครนัสสำหรับรายการ URL ที่เรียกต่อเนื่องกันโดยใช้ forEach (และ a for loop) จะทำให้คำขอที่เหลือถูกยกเลิก ฉันเปลี่ยนเป็นซิงโครนัสและทำงานได้ตามที่ตั้งใจไว้
การใช้คำขอ HTTP แบบซิงโครนัสเป็นแนวทางปฏิบัติทั่วไปในธุรกิจโฆษณาบนอุปกรณ์เคลื่อนที่
บริษัท (หรือที่เรียกว่า "ผู้เผยแพร่โฆษณา") ที่สร้างแอปพลิเคชันมักเรียกใช้โฆษณาเพื่อสร้างรายได้ ด้วยเหตุนี้พวกเขาจึงติดตั้ง SDK โฆษณาลงในแอปของตน มีอยู่มากมาย (MoPub, Ogury, TapJob, AppNext, Google Ads AdMob)
SDK เหล่านี้จะแสดงโฆษณาในมุมมองเว็บ
เมื่อแสดงโฆษณาแก่ผู้ใช้จะต้องมีประสบการณ์ที่ราบรื่นโดยเฉพาะอย่างยิ่งเมื่อเล่นวิดีโอ ไม่ควรมีการบัฟเฟอร์หรือโหลดในขณะใด ๆ
เพื่อแก้ปัญหานี้precaching
ใช้ ที่โหลดสื่อ (รูปภาพ / วิดีโอ / ฯลฯ ) พร้อมกันในพื้นหลังของมุมมองเว็บ
ทำไมไม่ทำแบบอะซิงโครนัส
onload
เหตุการณ์เพื่อให้ทราบว่าโฆษณา "พร้อม" ที่จะแสดงต่อผู้ใช้เมื่อใดด้วยการเลิกใช้งานXMLHttpRequests แบบซิงโครนัสธุรกิจโฆษณามักจะถูกบังคับให้เปลี่ยนมาตรฐานในอนาคตเว้นแต่จะสามารถกำหนดวิธีอื่นได้
XHR แบบซิงโครนัสมีประโยชน์มากสำหรับการพัฒนาเครื่องมือและ / หรือกรอบงานภายใน (ที่ไม่ใช่การผลิต) ตัวอย่างเช่นคุณต้องการโหลดไลบรารีโค้ดพร้อมกันในการเข้าถึงครั้งแรกเช่นนี้:
get draw()
{
if (!_draw)
{
let file;
switch(config.option)
{
case 'svg':
file = 'svgdraw.js';
break;
case 'canvas':
file = 'canvasdraw.js';
break;
default:
file = 'webgldraw.js';
}
var request = new XMLHttpRequest();
request.open('GET', file, false);
request.send(null);
_draw = eval(request.responseText);
}
return _draw;
}
ก่อนที่คุณจะรู้สึกมึนงงและสำรอกความชั่วร้ายของ eval อย่างสุ่มสี่สุ่มห้าโปรดจำไว้ว่านี่เป็นเพียงการทดสอบในพื้นที่เท่านั้น สำหรับรุ่นที่ใช้งานจริง _draw จะถูกตั้งค่าไว้แล้ว
ดังนั้นรหัสของคุณอาจมีลักษณะดังนี้:
foo.drawLib.draw.something(); //loaded on demand
นี่เป็นเพียงตัวอย่างหนึ่งของสิ่งที่เป็นไปไม่ได้หากไม่มีการซิงค์ XHR คุณสามารถโหลดไลบรารีนี้ล่วงหน้าใช่หรือทำสัญญา / โทรกลับ แต่คุณไม่สามารถโหลด lib พร้อมกันโดยไม่ต้องซิงค์ XHR ลองคิดดูว่าสิ่งประเภทนี้สามารถล้างรหัสของคุณได้มากแค่ไหน ...
ขีด จำกัด ของสิ่งที่คุณสามารถทำได้กับสิ่งนี้สำหรับเครื่องมือและเฟรมเวิร์ก (ทำงานในพื้นที่) นั้นถูก จำกัด ด้วยจินตนาการของคุณเท่านั้น แม้ว่าจินตนาการจะมีข้อ จำกัด เล็กน้อยในโลกของ JavaScript
นี่เป็นเหตุผลที่ดีประการหนึ่ง ฉันต้องการทำคำขอ http จากนั้นเรียกคลิก () บนประเภทอินพุต = ไฟล์ขึ้นอยู่กับผลลัพธ์ สิ่งนี้ไม่สามารถทำได้ด้วย xhr แบบอะซิงโครนัสหรือการดึงข้อมูล การเรียกกลับสูญเสียบริบท "การดำเนินการของผู้ใช้" ดังนั้นการคลิกโทร () จึงถูกละเว้น xhr ซิงโครนัสบันทึกเบคอนของฉัน
onclick(event){
//here I can, but I don't want to.
//document.getElementById("myFileInput").click();
fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
.then((response)=>response.json())
.then(function (validResult) {
if (validResult.success) {
//here, I can't.
document.getElementById("myFileInput").click();
}
});
}