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

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

本文关键字:连接 服务器 浏览器 刷新 用户 执行 函数 何停止 异步 如果      更新时间:2023-09-26

我目前正在使用React.js和服务器端渲染,其中我有多个异步调用从API服务器请求json。所以问题是,如果用户停止连接,函数继续执行,即使没有人为它服务。

例如,如果我按住刷新按钮,node.js Express服务器将继续发送数百个异步请求(可能也需要更长的时间来执行非异步函数),然后在收到响应后执行函数。

所以我需要一些方法来阻止函数在用户停止HTTP请求时触发,最坏的情况是按住刷新按钮。

我已经尝试使用res.end(),但是函数一直在触发。是否有一些聪明的方法来监听事件并停止异步或其他什么?

用"superagent"发出请求,用"async.js"发出请求

谢谢。

服务器上没有特别好的选项。

如果单个客户端从服务器发送多个请求,然后当请求正在处理或在服务器队列中等待处理时,最终用户点击刷新,则浏览器将删除/关闭当前打开的网页所具有的打开的Ajax套接字。

但是,已经在服务器上进行的请求将继续处理,服务器甚至不知道这些套接字已经关闭,直到服务器尝试写这些套接字。此时,它可能(取决于时间)发现套接字已关闭。但是,当然,到那时,您已经处理了请求并准备好了结果。也有可能在服务器意识到套接字已关闭之前就处理和发送请求。这将最终导致套接字上的错误(并导致套接字关闭),当没有从另一端返回响应或在等待发送的数据确认时从另一端返回关闭(因为TCP是一个可靠的协议,每次发送都必须由连接的另一端进行确认)。

所以,这一切都解释了为什么你真的不能在服务器上做很多事情。


如果客户端并行发送多个API请求,并且最终用户以某种方式导致在其中刷新页面,则您所描述的情况将会加剧。你可以做以下的事情来减少这个问题:

  1. 将多个请求合并为单个API请求。如果您的API已经允许这种类型的请求结构,那么切换到这种类型。或者,如果您控制了API,那么向API添加新功能,这样客户机就可以发送单个请求并在该请求中获取所有数据,而不是并行地发送多个请求。这限制了在网页关闭时可能被捕获的请求的数量。

  2. 限制发送的并行请求数。你可以通过使用Async库功能来实现这一点,该功能可以控制一次从你试图发送的请求列表中发送多少个请求,或者你可以序列化你的请求,这样一个请求只在前一个请求完成后发送。这也将限制在网页关闭时可能被捕获的请求数量。

  3. 如果您有一个特别昂贵的服务器端操作(一些可能需要几分钟才能运行的东西,比如构建一个大的报告文件),您可以设计一些与客户端的签入,然后在您的处理期间,您可以检查客户端是否仍然活动,如果不是,那么您可以中止自己的服务器端处理。对于大多数正常类型的服务器端请求,这可能不值得额外的麻烦(因为验证客户端仍处于活动状态有其自身的成本),但是如果您有一个特别昂贵的服务器端操作,您可以实现这样的东西。

  4. 如果您在请求处理中有异步操作,并且如果您愿意在每个异步操作后将检查放入请求处理中,那么您可以为'close'req.connection.addListener('close', function () { ... });注册侦听器,然后在该请求上设置某种标记,您在每个异步操作后检查该标记,然后在该连接上发现该标记时中止其余的请求处理。我在net模块文档中搜索了套接字对象上的一些标志或方法,这些标志或方法会告诉你它是否已经关闭(这样的信息应该在那里),但我在nodejs文档中找不到它。

中途终止请求不是async的工作。从async的角度来看,对服务器的请求只是一个单一的任务,不能再分割了。如果有可能这样做,它将是内置http模块或express的一部分。但我不确定这是否会很有帮助,即使有这样做的方法。当您尝试取消发送时,请求可能已经到达互联网。你真正想要的是一开始就不要发送那么多请求。

你还没有发布任何代码,所以我不能修改你的代码作为回应。而不是有一个事件处理程序,说"发送一个请求,并与响应做一些事情",写一个说"如果你没有发送一个请求在过去的2秒,发送一个,并与响应做一些事情,并将响应保存在一个变量;否则,查看变量的值,并假装您已经接收到它作为响应。(我假设所有的请求都是相同的——如果不是,那么你需要多考虑一下。)