在优先 AJAX 请求的情况下,如何处理浏览器对每个域的并行请求限制?

假设给定以下情况:

我们的网站已经触发了大约 20 个请求(甚至更多).这些可以是任何类型的请求——我们不知道如何再次触发它们.在这个网站上,所有请求都针对相同的 url.请求可以有订阅的事件监听器.

There are about 20 requests (or even more) which has been triggered by our website. These can be any kind of requests - we don't know how to trigger them again. On this website, all the requests target the same url. The requests can have subscribed event listeners.

在使用 Chrome 的情况下,前 6 个请求被发送,其他请求在队列中等待发送(因为 每个域的并行请求限制).

In case of using Chrome, the first 6 requests are sent and the others are waiting in a queue to be sent (because of the parallel request limit per domain).

此时网页触发了一个非常重要的请求(我们称之为VIR"),该请求比之前的 20 个请求具有更高的优先级发送到服务器.其他请求(及其事件侦听器)也很重要,因此我们不能只是中止它们以立即发送 VIR.

At this moment the webpage triggers a very important request (lets call it "VIR") which has a higher priority to be sent to the server then the previous 20 requests. The other requests (and their event listeners) are also kind of important so we can't just abort them to send the VIR immediately.

我们需要一个解决方案来获取所有挂起的请求(已发送 6 个 + 队列中的 14 个),中止它们,然后发送 VIR,然后再次发送其他请求,并附加相同的事件侦听器他们以前有过.

We need a solution to get all the pending requests (6 sent + 14 in the queue), abort them, then send the VIR, and then send the others again with the same event listeners attached that they had before.

如果没有其他(开箱即用)解决方案,两个基本问题是:

In case of no other (out of the box) solution, the 2 basic questions are:

  • 是否可以获得对所有待处理请求(包括队列)的引用?
  • 是否可以中止 xhr 然后再次发送(通过某种方式克隆它们,或者我不知道)?

还有一个相关的问题:

  • 我记得每个主机名的并行请求限制是对浏览器的限制,而不是仅针对当前选项卡的限制.有没有神奇的解决方案来处理它?如果是,我真的想写吗?:)

请注意,所有请求都必须发送到同一个域.(意味着此处不能选择使用 VIR 定位不同的域).但是使用 websocket 或 http/2 可以解决基本问题,这些不是当前问题中的选项.

Be aware of that all the requests have to be sent the same domain. (Means that targeting a different domain with the VIR is not an option here). However using websocket or http/2 could solve the basic problem, those are not options in this current question.

我很感激对此的任何想法!提前谢谢!

I appreciate any idea on this! Thx in advance!

pm.: 是的,这是一个 javascript 问题 :)

pm.: And yes, it's a javascript question :)

推荐答案

你实际上可以在中止请求、再次调用 open 和 send 方法以及事件监听器后继续使用相同的 XmlHttpRequest 实例保持依附.更新了代码片段,重载了 xhr open/send 方法以保存 url 和有效负载:

You can actually keep using the same XmlHttpRequest instance after aborting the request, calling the open and send methods again, and the event listeners remain attached. Updated the snippet with overloading the xhr open/send method to save the url and payload:

var pending_requests = [], 
    XHRBase = {
      open: XMLHttpRequest.prototype.open, 
      send: XMLHttpRequest.prototype.send
    };

XMLHttpRequest.prototype.open = function() {

  pending_requests.push(xhr._data = {xhr: this, open: arguments});
  XHRBase.open.apply(this, arguments);
  // add event listener to pop on finish
}

XMLHttpRequest.prototype.send = function() {
  xhr._data.send = arguments;
  XHRBase.send.apply(this, arguments);
}

function priority_call(params, callback) {
  pending_requests.forEach((req) => req.xhr.abort());
  // do vip xhr
  pending_requests.forEach((req) => {
    XHRBase.open.apply(req.xhr, req.open); 
    XHRBase.send.apply(req.xhr, req.send);
  })
}

相关文章