使用“卸载”自动保存注销时的事件和 ajax 调用:操作顺序导致问题

发布于 2024-11-15 00:03:54 字数 388 浏览 2 评论 0原文

我正在在线编辑器上使用自动保存功能。

当用户离开页面时(通过 unloadbeforeunload 事件检测到),我将发送 AJAX 请求 (async = false) 来保存数据。

我在 Firefox 中遇到问题,有时在 Chrome 中遇到问题,因为发生了一系列事件:

  • 事件触发的
  • 请求发送
  • 页面更改,并且用户断开连接
  • 由服务器分析的请求 =>问题 !
  • 浏览器收到的请求响应

当然,由于用户已断开连接,因此无法处理“保存”请求。

有没有一种方法可以与所有浏览器兼容,在页面实际更改之前等待 AJAX 调用的响应?

I'm using a AutoSave feature on an online editor.

When an user leaves the page (detected with unload or beforeunload event), I'm sending a AJAX request (async = false) to save the data.

I have a problem in Firefox et sometimes in Chrome because that serie of events is happening :

  • event fired
  • request send
  • the page change and the user is disconnected
  • request analysed by the server => problem !
  • request response received by browser

Of course since the user has been disconnected the "save" request can't be handled.

Is there a way, compatible with all browsers, to wait for the response of the AJAX call, before the page actually changes ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南街九尾狐 2024-11-22 00:03:54

ori的答案是正确且完整的。

但从你的情况来看,你可以使用解决方法。

您可能对两个 JavaScript 功能感兴趣:
localStorage 和 sessionStorage (除了第二个在浏览器关闭时被清除之外,它是相同的,因此您可能会选择第一个)

其想法是将数据保存到 localStorage ,并使用一些元数据说明是否保存了更改。如果用户离开页面但转到服务中的另一个页面,甚至稍后返回 - 您可以再次发送数据,并包含一些由于页面卸载而未保存的信息。

概念验证代码:

$(window).bind('unload', function() {
    localStorage.setItem('unsavedData',data);
    localStorage.setItem('unsaved',true);
});

$(document).ready(function(){
    if(localStorage.getItem('unsaved')){
       //ajax send 
       localStorage.setItem('unsaved',false);
    }
});

[编辑]

我已经成功地将 JSONP 与 unload 一起使用,并且它似乎在大多数情况下都能工作,但我还没有在负载和慢速网络上测试它。

ori's answer is correct and complete.

But judging from your case you could use a workaround.

There are two JavaScript features you might be interested in:
localStorage and sessionStorage (it's the same except the second one is cleared on browser close, so you probabli will choose the first)

The idea is to save data to localStorage with some metadata stating if changes were saved. If the user leaves the page but goes to another page in your service, or even returns later - you can send the data again with some information that it was not saved due to page unload.

Proof of concept code:

$(window).bind('unload', function() {
    localStorage.setItem('unsavedData',data);
    localStorage.setItem('unsaved',true);
});

$(document).ready(function(){
    if(localStorage.getItem('unsaved')){
       //ajax send 
       localStorage.setItem('unsaved',false);
    }
});

[edit]

I have been successfully using JSONP with unload and it seemed to work most of the times, but I haven't tested it under load and on slow network.

早茶月光 2024-11-22 00:03:54

不可以。您只能向用户显示一个确认对话框:

$(window).bind('beforeunload', function() {
    // AJAX

    return 'STRING';
});

STRING 将显示在对话框中,然后您可能有时间在用户做出反应之前返回响应。

但这是阻止页面卸载的唯一方法,因此不会收到 ajax 响应。

No. You can only display a confirm dialog to the user:

$(window).bind('beforeunload', function() {
    // AJAX

    return 'STRING';
});

The STRING will be displayed in the dialog, and then you might have time for the reponse to come back before user reacts.

But that's the only way you can block a page from unloading, hence the ajax response will not be received.

烂人 2024-11-22 00:03:54

在页面顶部放置一个固定的透明 div,并通过悬停事件来触发保存怎么样?只是从创造性的角度思考...保留您现在拥有的保存,但作为故障保护,我在想如果普通用户要导航离开,首先他们会将鼠标移至地址栏、后退按钮,或关闭按钮。如果您捕获 DOM 窗口的顶部,也许会在最后一刻获得更多成功的保存?

另外,您可以在 setTimeout() 上推送更改,但听起来您正在寻求比我的两个解决方案更有限的东西。

What about a fixed transparent div across the top of your page with a hover event to fire the save? Just thinking form a creative point of view... Keep the save you have now, but as a failsafe, I'm thinking if the average user is going to navigate away, first they will move the mouse to the address bar, back button, or close button. If you capture the top of the DOM Window, maybe get a few more successful last-minute saves?

Also, you could push the changes on a setTimeout() but it sounds like you're going for something more finite than both of my solutions.

野鹿林 2024-11-22 00:03:54

将 async 变为 false 会更容易。

否则,您可以使用 async:true 调用服务器,当它成功返回或出现错误时,您可以引发注销/重定向/错误消息的自定义事件。

悬停的透明 div 可用于让用户等待服务器响应。

Turning async to false would be easier thing to do.

Otherwise you could call server with async:true and when it returns either successfully or with error you can raise a custom event for logout/redirect/error message.

A hovering transparent div can be used to keep user waiting til the server responds.

仙气飘飘 2024-11-22 00:03:54

我正在使用 onbeforeunload 进行类似的操作,但我的数据有效负载非常小(一个 guid),并且我不需要任何返回值,所以它是即发即忘。它在 95% 的时间内有效,但不同的浏览器以不同的方式实现 onbeforeunload、onunload 等。

您可以弹出另一个窗口,其中包含未保存的数据,然后在请求触发后关闭该窗口,但这里的关键元素是“pop” - 很可能会被阻止。上面的本地存储答案可以用这个。

当然,第一个解决方案 - 询问用户,然后让他们保存可能是最好的。也许他们正在关闭以防止保存自上次保存以来的任何更改?

I am using onbeforeunload for something similar, but my data payload is quite small (a guid), and I don't need any return value, so it's fire and forget. It works around 95% of the time, but different browsers implement onbeforeunload, onunload, etc differently.

You could pop another window with the unsaved data, then close that window once your request has fired, but the key element here is 'pop' - chances are, that'll be blocked. T local storage answer above could be used by this.

Of course, the first solution - ask user, then let them save is probably the best. Perhaps they're closing to prevent saving any changes since the last save?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文