Search code examples
javascriptevent-handlingxmlhttprequestonbeforeunload

JavaScript: don't unload document until HttpRequest is complete


I need to make sure that when someone reloads or closes my page, their progress is saved. To save progress, I do a POST via XMLHttpRequest(), sending the data to server. I'm triggering this saveData() function inside a window.onbeforeunload event.

The problem is, that saveData() does some calculations, and then calls a sendData(content) to finally actually POST the data. And if the data I'm processing&sending is large (>100kB), the window seems to close before all the data gets through to the server. (I'm sending an image, and some times I only get half of it on the other side)

The http request is synchronous, xhr.open("POST", url, false), but that doesn't seem to cut it.

So my question is, how can I keep the onbeforeunload function from terminating, UNTIL xhr.readyState == 4? How do I make it wait for that event?

Oh, and setTimeout() will not work. The window will close before the "Time" comes.

This won't work:

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

Thanks for any insight!

PS: this shouldn't be "bad practice" since it only takes a few of seconds and I don't want the user to have to save manually. Also, saving while he works (as in, before he closes window), would slow down the app so I can't do that.

[EDIT] As a temporary measure, I resorted to using this trick to auto save the data if the user decides to stay on the page. However, I'd really like to not need to use any alert messages. :(


Solution

  • Disallowing the browser to do it's normal behaviour is normally a bad idea. And with onbeforeunload you can't pause the unload, you can only let the user know, that he/she is leaving the page and then let them decide, whether or not to leave the page - and thus the data unsaved.

    So i your case, i would suggest an draft autosave, like you see in Google documents + a warning when the user leaves the page with unsaved data.