JavaScript: jangan membongkar dokumen sampai HttpRequest selesai

Saya perlu memastikan bahwa ketika seseorang memuat ulang atau menutup halaman saya, kemajuannya disimpan. Untuk menyimpan kemajuan, saya melakukan POST melalui XMLHttpRequest(), mengirimkan data ke server. Saya memicu fungsi saveData() ini di dalam acara window.onbeforeunload.

Masalahnya adalah, saveData() melakukan beberapa perhitungan, dan kemudian memanggil sendData(content) untuk akhirnya benar-benar POST datanya. Dan jika data yang saya proses & kirim berukuran besar (>100kB), jendelanya sepertinya tertutup sebelum semua data sampai ke server. (Saya mengirim gambar, dan terkadang saya hanya mendapatkan setengahnya di sisi lain)

Permintaan http sinkron, xhr.open("POST", url, false), tapi sepertinya itu tidak cukup.

Jadi pertanyaan saya adalah, bagaimana caranya agar fungsi onbeforeunload tidak berhenti, SAMPAI xhr.readyState == 4? Bagaimana cara membuatnya menunggu acara itu?

Oh, dan setTimeout() tidak akan berfungsi. Jendela akan ditutup sebelum "Waktu" tiba.

Ini tidak akan berhasil:

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

Terima kasih atas wawasannya!

PS: ini seharusnya bukan "praktik buruk" karena hanya membutuhkan beberapa detik dan saya tidak ingin pengguna harus menyimpan secara manual. Selain itu, menyimpan saat dia bekerja (seperti, sebelum dia menutup jendela), akan memperlambat aplikasi jadi saya tidak bisa melakukan itu.

[EDIT] Sebagai tindakan sementara, saya terpaksa menggunakan trik ini untuk menyimpan data secara otomatis jika pengguna memutuskan untuk tetap berada di halaman. Namun, saya benar-benar ingin tidak perlu menggunakan pesan peringatan apa pun. :(


person Spectraljump    schedule 25.02.2011    source sumber


Jawaban (2)


Melarang browser melakukan perilaku normal biasanya merupakan ide yang buruk. Dan dengan onbeforeunload Anda tidak dapat menjeda pembongkaran, Anda hanya dapat memberi tahu pengguna, bahwa dia akan meninggalkan halaman dan kemudian membiarkan mereka memutuskan, apakah akan meninggalkan halaman atau tidak - dan dengan demikian data tidak disimpan.

Jadi dalam kasus Anda, saya akan menyarankan draf penyimpanan otomatis, seperti yang Anda lihat di dokumen Google + peringatan ketika pengguna meninggalkan halaman dengan data yang belum disimpan.

person Tokimon    schedule 25.02.2011
comment
Saya setuju. Tapi saya sangat benci jika situs menghentikan pengguna dengan popup dan meminta mereka untuk menyimpan. Dalam kasus saya, tidak mungkin dia tidak ingin menyimpan, dan itu membutuhkan waktu 3 detik. Tapi ternyata itu menyusahkan... - person Spectraljump; 25.02.2011

Sebenarnya Anda bisa memperlambat browser sebelum melakukan bongkar. Masalahnya terletak pada bagaimana JS menangani permintaan ajax.

Beberapa waktu yang lalu saya harus melakukan peretasan cepat dan kotor tentang hal yang hampir sama - mencatat beberapa hal, sebelum melakukan navigasi. Satu-satunya cara yang saya lakukan adalah menunggu nilai pengembalian permintaan XHR.

Meskipun sinkron, eksekusi kode bercabang di latar belakang dan tidak benar-benar memblokir browser. Anda harus mendapatkan nilai kembalian agar dapat menghentikan skrip untuk mengunggah data.

Ingatlah bahwa saya menggunakan jQuery untuk ini, tetapi ini berlaku untuk JS asli (menurut saya.. :))

/* 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 */

Semoga membantu.

person bisko    schedule 25.02.2011
comment
Terima kasih atas trik coba-tangkapnya. Namun, tampaknya ini berfungsi untuk penyegaran tetapi tidak untuk jarak dekat. Ini berarti browser (chrome) menutup paksa tab apa pun skripnya, berarti penyegaran membutuhkan waktu lebih lama dan skrip memiliki waktu untuk selesai - dalam hal ini juga berarti saya salah melakukannya... Idenya adalah menggunakan try{}catch(){} untuk menunggu fungsi ajax mengembalikan nilai, bukan? - person Spectraljump; 25.02.2011
comment
[perbarui] Pada dasarnya, jika saya memasukkan alert() setelah var asd = jQuery.ajax(request);, tidak akan pernah terpicu jika saya menutup tab. Ini berfungsi untuk penyegaran. - person Spectraljump; 25.02.2011