JavaScript: อย่ายกเลิกการโหลดเอกสารจนกว่า HttpRequest จะเสร็จสมบูรณ์

ฉันต้องแน่ใจว่าเมื่อมีคนโหลดซ้ำหรือปิดเพจของฉัน ความคืบหน้าของพวกเขาจะถูกบันทึกไว้ เพื่อบันทึกความคืบหน้า ฉันทำการ POST ผ่าน XMLHttpRequest() โดยส่งข้อมูลไปยังเซิร์ฟเวอร์ ฉันกำลังเรียกใช้ฟังก์ชัน saveData() นี้ภายในเหตุการณ์ window.onbeforeunload

ปัญหาคือ saveData() ทำการคำนวณบางอย่าง จากนั้นจึงเรียก sendData(content) เพื่อ POST ข้อมูลจริงในที่สุด และหากข้อมูลที่ฉันกำลังประมวลผลและส่งมีขนาดใหญ่ (>100kB) หน้าต่างดูเหมือนจะปิดลงก่อนที่ข้อมูลทั้งหมดจะถูกส่งไปยังเซิร์ฟเวอร์ (กำลังส่งภาพอยู่ครับ บางทีก็อีกฝั่งได้แค่ครึ่งเดียว)

คำขอ http เป็นแบบซิงโครนัส xhr.open("POST", url, false) แต่ดูเหมือนจะไม่ลดทอนลง

ดังนั้นคำถามของฉันคือ ฉันจะรักษาฟังก์ชัน onbeforeunload ไม่ให้ยุติได้อย่างไร UNTIL xhr.readyState == 4 ฉันจะทำให้รอเหตุการณ์นั้นได้อย่างไร?

โอ้ และ setTimeout() จะไม่ทำงาน หน้าต่างจะปิดก่อน "เวลา" จะมาถึง

สิ่งนี้จะไม่ทำงาน:

if (!jQuery) {
    setTimeout(attachCode, 100);
    return;
} else {
    // continue and close
}

ขอบคุณสำหรับข้อมูลเชิงลึก!

PS: นี่ไม่ควรเป็น "แนวทางปฏิบัติที่ไม่ดี" เนื่องจากใช้เวลาเพียงไม่กี่วินาที และฉันไม่ต้องการให้ผู้ใช้บันทึกด้วยตนเอง นอกจากนี้ การบันทึกในขณะที่เขาทำงาน (เช่น ก่อนที่เขาจะปิดหน้าต่าง) จะทำให้แอปช้าลง ดังนั้นฉันจึงทำอย่างนั้นไม่ได้

[แก้ไข] เพื่อเป็นมาตรการชั่วคราว ฉันหันไปใช้ เคล็ดลับนี้ เพื่อบันทึกข้อมูลอัตโนมัติหากผู้ใช้ตัดสินใจที่จะอยู่ในหน้านั้นต่อไป อย่างไรก็ตาม ฉันไม่ต้องการใช้ข้อความแจ้งเตือนใดๆ เลย :(


person Spectraljump    schedule 25.02.2011    source แหล่งที่มา


คำตอบ (2)


การไม่อนุญาตให้เบราว์เซอร์ทำงานตามปกติถือเป็นความคิดที่ไม่ดี และด้วย onbeforeunload คุณจะไม่สามารถหยุดการยกเลิกการโหลดชั่วคราวได้ คุณทำได้เพียงแจ้งให้ผู้ใช้ทราบว่าเขา/เธอกำลังจะออกจากเพจ แล้วให้พวกเขาตัดสินใจว่าจะออกจากเพจหรือไม่ - และข้อมูลจึงไม่ได้ถูกบันทึก

ในกรณีของคุณ ฉันขอแนะนำให้บันทึกอัตโนมัติแบบร่าง เหมือนที่คุณเห็นในเอกสาร Google + คำเตือนเมื่อผู้ใช้ออกจากหน้าพร้อมกับข้อมูลที่ยังไม่ได้บันทึก

person Tokimon    schedule 25.02.2011
comment
ฉันเห็นด้วย. แต่ฉันเกลียดมันจริงๆ เมื่อไซต์หยุดผู้ใช้ด้วยป๊อปอัปและขอให้พวกเขาบันทึก ในกรณีของฉัน ไม่มีทางที่เขาไม่อยากช่วย และมันใช้เวลา 3 วินาที กลับกลายเป็นเรื่องลำบากใจ... - person Spectraljump; 25.02.2011

จริงๆ แล้วคุณสามารถชะลอเบราว์เซอร์ก่อนที่จะยกเลิกการโหลดได้ ปัญหาอยู่ที่ว่า JS จัดการกับคำขอ ajax อย่างไร

เมื่อไม่นานมานี้ ฉันต้องทำแฮ็กอย่างรวดเร็วและสกปรกเกี่ยวกับสิ่งเดียวกันเกือบทั้งหมด นั่นคือการบันทึกบางสิ่งก่อนที่จะนำทาง วิธีเดียวที่ฉันพบว่าทำได้คือรอค่าส่งคืนของคำขอ XHR

แม้ว่าจะเป็นแบบซิงโครนัส แต่การเรียกใช้โค้ดในพื้นหลังและไม่ได้บล็อกเบราว์เซอร์จริงๆ คุณต้องได้รับค่าที่ส่งคืนจึงจะสามารถหยุดสคริปต์เพื่ออัปโหลดข้อมูลได้

โปรดทราบว่าฉันใช้ jQuery สำหรับสิ่งนี้ แต่มันใช้ได้กับ JS ดั้งเดิม (ฉันคิดว่า .. :))

/* some code above */
var request = {
    async:false,
    cache: false,
    url: this.serviceURL,
    type: 'POST',
    data: {...},
    success: function(data) {}
};
try {
    var asd = $j.ajax(request); // do the request and wait
}
catch (e) {}
/* some code below */

ฉันหวังว่านี่จะช่วยได้.

person bisko    schedule 25.02.2011
comment
ขอบคุณสำหรับเคล็ดลับการลองจับ อย่างไรก็ตาม ดูเหมือนว่าจะใช้งานได้สำหรับการรีเฟรชแต่ไม่ได้ผลสำหรับการปิด นี่หมายความว่าเบราว์เซอร์ (chrome) บังคับปิดแท็บโดยไม่คำนึงถึงสคริปต์ หมายความว่าการรีเฟรชใช้เวลานานกว่าและสคริปต์มีเวลาเสร็จสิ้น - ซึ่งในกรณีนี้ก็หมายความว่าฉันทำผิด... แนวคิดคือการใช้ try{}catch(){} เพื่อรอให้ฟังก์ชัน ajax ส่งกลับค่าใช่ไหม - person Spectraljump; 25.02.2011
comment
[อัปเดต] โดยพื้นฐานแล้ว หากฉันแทรก alert() หลัง var asd = jQuery.ajax(request); มันจะไม่ถูกทริกเกอร์หากฉันปิดแท็บ มันใช้งานได้สำหรับการรีเฟรช - person Spectraljump; 25.02.2011