Javascript承诺等待彼此

时间:2017-07-04 15:03:10

标签: javascript promise

我有这个用于管理仪表板的代码,其中包含大约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);
            });
        });
}

1 个答案:

答案 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

Delay chained promise

  

出乎意料的是,即使所有100个请求都是在页面加载后立即发送的,它们也只是一次只能解决,并且(大致)按照它们发送的顺序解决。粗略地意味着3个,2个,5个,1个,8个......但是我期待像3,89,12,76,21,94 ......这样的东西似乎有多少限制承诺可以同时运行,也可以按照什么顺序运行。

另一个会影响你的ajax调用的是每个浏览器对同一主机允许的并发ajax调用数量有限制。如果超过该限制,它将对它们进行排队,而不是运行后续的,直到某些早期完成。每个浏览器都设置了自己的限制,并且它们随着时间的推移而发生了变化,所以我不确切地知道当前的限制是什么,但它们是低的。我知道Chrome在同一台主机上曾经是6个。因此,这也会影响事情完成的确切顺序。

当您达到此限制时,Ajax调用将按您的代码调用的顺序发送。因此,如果每个主机的限制为6,那么您的前6个将被发送,第7个请求将仅在前6个中的一个完成时发送,依此类推。这仍然不能保证完成订单,但它确实会影响以后的请求在之前的请求之前完成的能力。