Javascript 可以使用卸载事件可靠地触发 ajax 请求吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3584288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:18:39  来源:igfitidea点击:

Can the unload Event be Used to Reliably fire ajax Request?

javascriptajaxeventsreliability

提问by Yi Jiang

I need a method to monitor user edit sessions, and one of the solutions I'm reviewing will have me using an unloadevent to send an ajax request to inform the server of the end of the edit session. (See: Monitoring User Sessions to Prevent Editing Conflict)

我需要一种方法来监视用户编辑会话,我正在的解决方案之一将让我使用unload事件发送 ajax 请求以通知服务器编辑会话结束。(请参阅:监控用户会话以防止编辑冲突

My (rather limited) reading on the unloadevent indicate that the codes attached to this handler has to run quickly, and as such is usually used for clearing objects to prevent memory leaks.

我对unload事件的(相当有限的)阅读表明附加到此处理程序的代码必须快速运行,因此通常用于清除对象以防止内存泄漏。

My question is, can this work reliably enough for this purpose?

我的问题是,为此目的,这项工作是否足够可靠?

PS. I know about the async: falseoption.

附注。我知道这个async: false选项。

采纳答案by Ilya Volodin

This method is fairly reliable, if your server is fast enough to respond. Something to really watch out for though. If you close the browser and send AJAX request on unload event, there's a very good chance that the response isn't going to come back from the server in time before the window object is destroyed. What happens in this case (at least with IE) is that it will orphan your connection object and not terminate it correctly until the connection timeout is hit. If your server doesn't have connection keep-alive turned on, after you close 2 windows (while still having another window open), you will run out of open connections to the server (for IE6-7, for IE8 - 6 windows) and you will not be able to open your website until your connection timeout is hit.

如果您的服务器足够快以进行响应,则此方法相当可靠。不过确实需要注意一些事情。如果关闭浏览器并在卸载事件时发送 AJAX 请求,则很有可能在窗口对象被销毁之前响应不会及时从服务器返回。在这种情况下(至少对于 IE)会发生什么,它将孤立您的连接对象,并且在连接超时之前不会正确终止它。如果您的服务器没有打开连接保持连接,在您关闭 2 个窗口后(同时仍然打开另一个窗口),您将耗尽与服务器的开放连接(对于 IE6-7,对于 IE8-6 窗口)在达到连接超时之前,您将无法打开您的网站。

I ran into a situation like that before were I was opening a popup window that was sending an AJAX request on unload, it was very reliable, but it was plagued by the issued described above, and it took really long time for me to track it down and understand what's going on. After that, what I did, is I made sure that opening window would have the same code to call server, and on every unload checked for the opener and ran the code there if it was present.

我之前遇到过这样的情况,当我打开一个在卸载时发送 AJAX 请求的弹出窗口时,它非常可靠,但它被上述问题所困扰,我花了很长时间来跟踪它下来并了解发生了什么。在那之后,我所做的是确保打开的窗口将具有相同的代码来调用服务器,并且在每次卸载时检查开启器并在那里运行代码(如果存在)。

It seems that if you close the very last browser window, IE will destroy connection properly, but if one other window is open, it will not.

似乎如果您关闭最后一个浏览器窗口,IE 会正确地破坏连接,但如果打开另一个窗口,则不会。

P.S. And just to comment on the answer above, AJAX is not really async. At least JS implementation of it isn't. After you send a request, you JS code is still going to be waiting for response from the server. It's not going to block your code execution, but since the server might take a while to response (or long enough for Windows to terminate IE window object) you might and probably will run into the problem described above.

PS 只是为了评论上面的答案,AJAX 并不是真正的异步。至少它的 JS 实现不是。发送请求后,您的 JS 代码仍将等待服务器的响应。它不会阻止您的代码执行,但由于服务器可能需要一段时间来响应(或足够长的时间让 Windows 终止 IE 窗口对象),您可能并且可能会遇到上述问题。

回答by Slawek

Have you tried to use

你有没有试过使用

var i = new Image(1,1); 
i.src='http://...'

And just returning some empty image from server. I think it should be reliable, script will block. BTW: nice to add timestamp to prevent caching.

并且只是从服务器返回一些空图像。我认为它应该是可靠的,脚本会阻塞。顺便说一句:很高兴添加时间戳以防止缓存。

回答by Juan Mendes

We have a case where we needed that. It's a report page that needs serious memory on the server so we wanted to free it immediately as soon as they left the page. We created a frameset and added the unload handler there. The most reliable way was to set the src of an image to the freeing script. We actually used both the unload and onbeforeunload for cross browser compatibility. It didn't work in web kit nightlies but management was OK with that.

我们有一个需要它的案例。这是一个报告页面,需要大量的服务器内存,所以我们想在他们离开页面后立即释放它。我们创建了一个框架集并在那里添加了卸载处理程序。最可靠的方法是将图像的 src 设置为释放脚本。我们实际上同时使用了 unload 和 onbeforeunload 来实现跨浏览器兼容性。它在 web kit nightlies 中不起作用,但管理人员对此没有意见。

However, that was not my proposed solution. I would use a heartbeat approach which involves more work but is much more robust.

然而,这不是我提出的解决方案。我会使用心跳方法,它涉及更多的工作,但更强大。

Your page should send out periodical heartbeat requests. Each request sets the last heartbeat from a page. You then need a thread that runs on the server and clears memory if the last heartbeat was too long ago.

您的页面应该定期发送心跳请求。每个请求都会设置页面的最后一个心跳。然后,您需要一个在服务器上运行的线程,并在上次心跳时间太久之前清除内存。

This doesn't solve the problem of leaving the page up for a long time. For that you need some monitoring for user activity and leave that page after a period of inactivity (make sure you confirm with the user)

这并不能解决长时间离开页面的问题。为此,您需要对用户活动进行一些监控,并在一段时间不活动后离开该页面(确保与用户确认)

回答by palswim

You'll have to do your own testing about whether or not your particular scenario works with the time you have in unload, but making the AJAX request is pretty fast, since AJAX is asynchronous. You just send the request and then you're done! (Maybe you'll have to clear the request object you just created, though.)

您必须自己测试您的特定场景是否适合您的时间unload,但发出 AJAX 请求非常快,因为 AJAX 是异步的。您只需发送请求,然后就完成了!(不过,也许您必须清除刚刚创建的请求对象。)

If you wanted to verify that the AJAX request made it, then you'd have to worry more/use the async:falseoption (like this discussionindicates). But, just sending is a quick boom-and-you're-done operation.

如果您想验证 AJAX 请求是否成功,那么您必须更加担心/使用该async:false选项(如本讨论所示)。但是,只是发送是一个快速的繁荣,你就完成了操作。

回答by eric.itzhak

I had a case in which I only needed to notify server side about the unload and didn't care about the response.

我有一个案例,我只需要通知服务器端有关卸载的信息,而不关心响应。

If thats your case you can ignore_user_abortand then you know it'll happen "reliably"

如果那是你的情况,你可以ignore_user_abort然后你知道它会“可靠地”发生