冒着因未发布代码而被烤的风险,解决ajax请求的6个并发调用限制的最佳方法是什么?
因此,当前我正在使用的应用程序在页面加载时最多可以有40个左右的ajax请求。对于背景,大多数这些请求是针对隐藏在选项卡后面的各种图形。用户可以触发一些请求(例如,在不刷新页面的情况下更新实体名称)。这意味着,由于并发请求受到限制,用户只有在运行其他5个请求后才能更改任何内容,这是不可接受的用户体验。
这可能意味着该应用程序的结构不良,但是大多数内容并不需要立即加载。
无论如何,我对fetch()和Webworkers进行了一些研究,但是找不到有关这些内容是否有助于克服限制的任何信息。
一种解决方案是将资源放在不同的子域中,但这会使后端API变得不必要地复杂(这是浏览器问题,而不是服务器问题)。
我已经考虑过以下方法:
答案 0 :(得分:1)
这是非常基于意见的。
40个请求并非没有道理,但是取决于您的服务器和站点设置,它可能需要一段时间。
有了这么多电话,我会将其中一些电话捆绑成一个initializePage=X
电话。这确实涉及服务器端的一些工作。
Delay requests
不一定很糟糕,具体取决于您预计的交付时间。如果可能的话,您可以呈现某种动画或“预期结果”,直到响应滴答滴答为止,以使用户感到满意。 Queing
的请求也是如此。
如果在服务器上运行大量初始化操作(例如安全检查),则重组代码以返回捆绑中的所有内容也可以极大地加快站点的速度。
如果仍然需要性能,则可以研究提供更快结果的连接,例如EventSource或WebSocket。这种更快的连接还允许使用更灵活的链接方法。例如,EventSource支持事件,因此您可以在一个捆绑请求中设置多个事件,并在服务器返回数据时将其触发。
Webworkers并不是答案,因为这里的问题是连接速度和并发连接限制。
答案 1 :(得分:1)
我认为我们不能直接回答这个问题。您提到的几种解决方案是可行的,但根据工作水平而有所不同。如果您愿意调整体系结构,可以考虑使用GraphQL方法来为您打包捆绑软件。我还要说的是,您可以维护REST,但是有一个特殊的代理服务可以为您捆绑数据。我还要说,不要让RESTfullness支配或强迫您发展。
在我看来,将请求延迟到用户需要之前,这似乎是适当的选择。这就是为什么我们要“超越折叠” CSS样式和无限滚动的基础。首先先加载所需的内容,然后在需要的时候推迟可能实际上无关紧要的内容。
答案 2 :(得分:1)
如果从一个线程中调用这些请求,则AJAX调用的并发性将会显现出来。如果将WebWorker与AJAX一起使用,则完全没有问题,原因是Webworker的每个实例都将被隔离在一个不在主线程中的线程中。
我称其为JaxWeb,我将在下周推出git repo,在那里您可能会找到处理该问题的纯JS代码。目前正在测试中,但是是的,确实可以解决问题。
示例:
在JaxWeb.js中添加以下代码
onmessage = function (e) {
var JaxWeb = function (e) {
return {
requestChannel: {},
get_csrf_token: function () {
return this._csrf_token;
},
set_csrf_token: function (_csrf_token = null) {
this._csrf_token = _csrf_token;
},
prepare: (function ( e ) {
this.requestChannel = new XMLHttpRequest();
this.requestChannel.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
postMessage(JSON.parse(this.responseText));
}
};
this.requestChannel.open(e.data.method, e.data.callname, true);
this.requestChannel.setRequestHeader("X-CSRF-TOKEN", e.data.token);
var postData = '';
if (e.data.data)
postData = JSON.stringify(e.data.data);
this.requestChannel.send(postData);
})(e)
}
};
return JaxWeb(e);
}
用法:
jaxWebGetServerResponse = function () {
var wk2 = new Worker('path_to_jaxweb_js/JaxWeb.js');
wk2.postMessage({
"callname": '<url end point>',
"method": '<your http method>',
"data": ''
});
wk2.onmessage = function (serverResponse) {
//
//process results
//with data that is received from server
}
};
//Invoke the function
jaxWebGetServerResponse();