简体   繁体   English

如果用户中止连接到服务器(连接时刷新,关闭浏览器等),如何停止执行所有功能(多个异步等)。

[英]How to stop all functions (multiple asyncs etc) from executing if user abort connecting to the server (refresh while connecting, close browser, etc..)

I'm currently working with React.js and Server-Side rendering where I have multiple async calls requesting json from API server. 我目前正在使用React.js和服务器端渲染,其中有多个异步调用从API服务器请求json。 So the problem is if user stops connecting, the functions keep executing even though it has nobody to serve it to. 因此,问题在于,如果用户停止连接,即使没有人提供服务,功能也会继续执行。

For example if I hold down refresh button, the node.js Express server will keep sending hundreds of async requests (and probably non async functions as well which take longer to execute) and then executing functions once received response. 例如,如果我按下刷新按钮,则node.js Express服务器将继续发送数百个异步请求(可能还需要花费更长的时间来执行非异步功能),然后在收到响应后立即执行功能。

So basically I need some way to stop functions from firing if user stops HTTP request, worst case if holding refresh button down... 所以基本上我需要一些方法来阻止用户停止HTTP请求时触发功能,最糟糕的情况是按住刷新按钮时...

I've tried to use res.end(), but the functions keep firing. 我尝试使用res.end(),但函数不断触发。 Is there some smart way to listen to an event and stop the async or something? 有什么聪明的方法可以监听事件并停止异步或其他操作吗?

requests are made with "superagent" and async with "async.js" 请求通过“ superagent”发出,并通过“ async.js”异步发出

Thanks. 谢谢。

There are no particularly great options for you on the server. 服务器上没有特别适合您的选择。

If a single client sends off multiple requests from the server and then while the requests are being processed or are in the server queue waiting to be processed, the end user hits refresh, then the browser will drop/close the open Ajax sockets that the currently open web page has. 如果单个客户端从服务器发出多个请求,然后在处理请求或在服务器队列中等待处理时,最终用户将单击“刷新”,那么浏览器将丢弃/关闭当前打开的Ajax套接字。打开网页了。

But, requests that are already underway on the server will continue to process and the server will not even know that those sockets have been closed until the server tries to write to those sockets. 但是,已经在服务器上进行的请求将继续处理,并且服务器甚至在服务器尝试写入这些套接字之前都不知道那些套接字已经关闭。 At that point, it may (depending upon timing) discover that the sockets have been closed. 此时,可能(取决于时间)发现插座已关闭。 But, of course by that time, you've already processed the requests and have the results ready to go. 但是,当然到那时,您已经处理了请求并准备好结果。 It may also occur that the request is processed and sent before the server is even aware that the sockets have been closed. 还可能在服务器甚至不知道套接字已关闭之前就处理并发送了请求。 This will eventually cause an error on the socket (and a resulting close of the socket) when no response comes back from the other end or a close comes back from the other end while awaiting confirmation of the data that was sent (since TCP is a reliable protocol, every send must be ACKed by the other end of the connection). 当等待确认发送的数据时,另一端没有响应,或者另一端关闭又返回,这将最终在套接字上导致错误(并导致套接字的关闭)(因为TCP是一个可靠的协议,每次发送都必须在连接的另一端进行确认)。

So, this all explains why there really isn't a whole lot you can do on the server. 因此,所有这些都解释了为什么在服务器上实际上没有很多可以做的事情。


The situation you describe will be exacerbated if the client is sending multiple API requests in parallel and the end-user is somehow led to refresh the page in the middle of that. 如果客户端并行发送多个API请求,并且最终用户以某种方式导致在页面中间刷新页面,则您描述的情况将会恶化。 The things you can do to lessen this issue are as follows: 您可以采取以下措施来减轻此问题:

  1. Combine multiple requests into a single API request. 将多个请求合并为一个API请求。 If your API already permits that type of structuring of the request, then switch to that. 如果您的API已经允许这种类型的请求结构,请切换到该结构。 Or, if you control the API, then add new capabilities to the API so that rather than having a client send multiple requests in parallel, it can send a single request and get all the data in that one request. 或者,如果您控制API,则向API添加新功能,以便与其让客户端并行发送多个请求,不如让客户端发送单个请求并获取该请求中的所有数据。 This limits the number of requests that might get caught in process when the web page is closed. 这限制了在关闭网页时可能被处理的请求的数量。

  2. Limit the number of parallel requests you send. 限制您发送的并行请求数。 You can do this either by using the Async library feature that controls how many requests are sent at once from a list of requests you're trying to send or you can serialize your requests so one is sent only after the previous one finishes. 您可以通过使用异步库功能来执行此操作,该功能可控制要发送的请求列表中一次发送的请求数量,或者可以序列化请求,以便仅在前一个请求完成后才发送请求。 This would also limit the number of requests that might get caught in process when the web page is closed. 这也将限制在关闭网页时可能被处理的请求数。

  3. If you had a particularly expensive server-side operation (something that might take minutes to run such as building a large report file), you could devise some sort of check-in with the client and then during your processing you could check to see if the client was still active and if not, then you could abort your own server-side processing. 如果您在服务器端进行了特别昂贵的操作(可能需要花费几分钟的时间才能运行,例如构建大型报告文件),则可以设计与客户端的某种签入,然后在处理过程中检查一下是否客户端仍处于活动状态,如果没有,则可以中止自己的服务器端处理。 For most normal types of server-side requests, this would probably not be worth the extra trouble (since verifying the client is still active has its own cost), but if you have a particularly costly server-side operation, you could implement something like this. 对于大多数普通类型的服务器端请求,这可能不值得付出额外的麻烦(因为验证客户端仍处于活动状态需要自己承担费用),但是如果您的服务器端操作成本特别高,则可以实现类似这个。

  4. If you have async operations in your request processing and if you're willing to put checks into your request handling after each async operation, then you could register a listener for the 'close' with req.connection.addListener('close', function () { ... }); 如果您在请求处理有异步操作,如果你愿意把支票存入您的请求处理每个异步操作后,那么你可以在注册一个侦听器'close'req.connection.addListener('close', function () { ... }); , then set some sort of flag on that request that you check after each async operation and then abort the rest of the request processing whenever you discover that flag on that connection. ,然后在每次异步操作后检查该请求的请求上设置某种标志,然后在发现该连接上的该标志时中止其余请求处理。 I scoured the net module docs for some flag or method on the socket object that would tell you if it's already been closed (such information should be there), but I could not find it mentioned in the nodejs doc. 我在net模块文档中搜索了套接字对象上的一些标志或方法,这些标志或方法会告诉您它是否已关闭(此类信息应该存在),但在nodejs文档中找不到它。

Aborting requests halfway through isn't the job of async . 中途中止请求不是async的工作。 From async 's point of view, a request to the server is just a single task that can't be split up any further. async的角度来看,对服务器的请求只是一个单独的任务,无法进一步拆分。 If it is possible to do something like this, it would be part of the built-in http module or express . 如果可以执行这样的操作,则它将成为内置http模块或express But I'm not sure that it would be very helpful, even if there is a way of doing it. 但是我不确定这是否会很有帮助,即使有办法可以做到。 The request has probably reached the internet by the time you try to unsend it. 您尝试取消发送请求时,请求可能已到达Internet。 What you really want is not to send so many requests in the first place. 您真正想要的是首先不要发送太多请求。

You haven't posted any code, so I can't write modifications to your code in response. 您尚未发布任何代码,因此我无法对您的代码进行修改。 Instead of having an event handler that says "send a request and do something with the response", write one that says "if you haven't sent a request in the last 2 seconds, send one and do something with the response, and also save the response in a variable; otherwise, look at the value of the variable and pretend you've received it as the response". 而不是让事件处理程序显示“发送请求并对响应进行某种处理”,而是写一个“如果您在最近2秒钟内未发送请求,则发送一个对响应进行处理,然后将响应保存在变量中;否则,请查看变量的值,并假装您已将其作为响应接收”。 (I'm assuming that all requests are identical - if not, then you need to think a bit more about it.) (我假设所有请求都是相同的-如果不完全相同,那么您需要多考虑一下。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 所有功能,事件等的浏览器兼容性代码 - Browser compatibility code for all functions, events, etc 将 ZeroMQ 从浏览器连接到服务器 - Connecting ZeroMQ from browser to server 如何在javascript或jquery中仅检测浏览器关闭按钮事件,不刷新页面等 - how to detect only browser close button event in javascript or jquery, No page refresh etc 我如何调用HTML DOM事件对象(例如:onclick,onblur等)的嵌套函数? - How can I call to HTML DOM Event Object (for example: onclick, onblur, etc..) nested functions? 如何阻止变量连接 - How to stop variables from connecting 如何在仍加载JavaScript的情况下继续使用页面(点击,任务等) - how to be able to keep using a page(clickin,tasks etc..) while a javascript is still being loaded 如何在 TextBox(用户、密码等)中缩进文本和光标的起始位置 - How can I indent the text, and starting position of cursor, in a TextBox (user, password, etc..) 浏览器未使用Websocket连接到服务器 - Browser not connecting to server with websocket 如何使用 PHP / CURL / Javascript 等从 mca.gov.in 获取公司详细信息? - how to get company details from mca.gov.in using PHP / CURL / Javascript etc..? 如何使用触发器等在准备就绪的文档上初始化我的功能? - how to initialize my function on document ready using trigger etc..?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM