我有这个用于管理仪表板的代码,其中包含大约100个独立检查。
通过AJAX调用接收检查结果。
每次检查都有一个初始请求。在收到特定检查的结果后,代码递归等待设置超时并再次为该检查重复请求。
一个承诺=一次检查。
我想知道为什么promises开始只解决之后每个都挂起(没有一个处于超时期限)。即使服务器的响应是“即时的”,它们只是等待循环中的最后一个承诺。
const TIMEOUT = 4000;
function checkForUpdate(environment, application, check) {
Dashboard.setCheckPending(environment, application, check);
return Communicator.getStatus(environment, application, check)
.then(status => {
Dashboard.updateCheckCell(environment, application, check, status);
Dashboard.updateEnvironmentCell(environment, application);
setTimeout(() => {
return checkForUpdate(environment, application, check)
},
TIMEOUT
);
});
}
Communicator.getEnvMatrix()
.then(data => {
Dashboard.create(data);
$.each(data, (environment, applications) => {
$.each(applications, (application, checks) => {
$.each(checks, (key, check) => {
checkForUpdate(environment, application, check);
});
});
});
});
问题还在于如何重写,以便每个检查等待它自己的结果和设置超时。
100个检查中的每一个都是独立的,这就是为什么我想尽快为每个检查运行AJAX(在$.each()
循环内)。
检查仅依赖于自身。我不希望它等待任何其他检查。
收到检查结果后,必须等待设置超时才能再次检索其状态。这就是我在setTimeout()
。
即使我重写(见下文)setTimeout()
作为承诺,但遗憾的是行为保持不变。
function delay(timeout) {
return new Promise(resolve => {
setTimeout(resolve, timeout);
});
}
function checkForUpdate(environment, application, check) {
Dashboard.setCheckPending(environment, application, check);
let promise = Communicator.getStatus(environment, application, check).promise();
return promise
.then(status => {
Dashboard.updateCheckCell(environment, application, check, status);
Dashboard.updateEnvironmentCell(environment, application);
return delay(TIMEOUT).then(() => {
return checkForUpdate(environment, application, check);
});
});
}
答案 0 :(得分:2)
您的代码同步运行$.each()
。这意味着它将在其他任何东西运行之前调用每个checkForUpdate()
。由于符合标准的promises总是异步解析(在某些未来的时间点),这意味着这里的每个请求都将在任何promise可以运行其.then()
处理程序之前启动。这是承诺的工作方式。只有完成$.each()
循环后,Javascript解释器才能开始处理已解决的承诺的.then()
处理程序。
另外,目前还不清楚为什么要在return checkForUpdate(environment, application, check)
内尝试setTimeout()
。 return
没有做任何事情。它只是回到setTimeout()
回调,什么都不做。父函数早已经返回,所以这不会将下一个checkForUpdate()
链接到前一个promise链。如果你想将它们链接在一起,那么你需要延迟一个承诺并返回这些承诺,如这些参考中所示:
using setTimeout on promise chain
Delays between promises in promise chain
出乎意料的是,即使所有100个请求都是在页面加载后立即发送的,它们也只是一次只能解决,并且(大致)按照它们发送的顺序解决。粗略地意味着3个,2个,5个,1个,8个......但是我期待像3,89,12,76,21,94 ......这样的东西似乎有多少限制承诺可以同时运行,也可以按照什么顺序运行。
另一个会影响你的ajax调用的是每个浏览器对同一主机允许的并发ajax调用数量有限制。如果超过该限制,它将对它们进行排队,而不是运行后续的,直到某些早期完成。每个浏览器都设置了自己的限制,并且它们随着时间的推移而发生了变化,所以我不确切地知道当前的限制是什么,但它们是低的。我知道Chrome在同一台主机上曾经是6个。因此,这也会影响事情完成的确切顺序。
当您达到此限制时,Ajax调用将按您的代码调用的顺序发送。因此,如果每个主机的限制为6,那么您的前6个将被发送,第7个请求将仅在前6个中的一个完成时发送,依此类推。这仍然不能保证完成订单,但它确实会影响以后的请求在之前的请求之前完成的能力。