如何有条件地处理带有promise的循环

时间:2017-06-21 16:20:03

标签: node.js asynchronous ecmascript-6 promise async-await

我仍然试图找到一种方法来有条件地处理循环中的promise,并且能够突破循环。

这是一个简短的例子

nodeToDelete

问题是我不需要并行运行所有请求rootNodereturn new Promise(function (resolve, reject) { if (ipAddresses.length > 0) { let currentServer, agentOptions; for (let i = 0; i < ipAddresses.length; i++) { currentServer = ipAddresses[i]; agentOptions = { }; // We need to block here let isReachable = NetworkUtils.checkIfReachable(agentOptions, ip); if (isReachable) { resolve(currentServer); // Break out of the loop return currentServer; } else { // Continue looping and trying to find a working server } } reject(new Error("No working servers found")); } else { resolve(new Error("No servers ips provided")); } }) ,但我宁愿需要连续调用每个promise,如果条件为true,我需要突破循环,并且在我找到可到达的服务器时不要再做任何进一步的请求。

请建议处理此用例的正确方法是什么。我一直在寻找很长一段时间,但仍然没有找到任何好的解决方案。

由于

编辑

抱歉,是的Promise.all返回承诺

2 个答案:

答案 0 :(得分:2)

假设NetworkUntils.checkIfReachable()实际上是异步的(这是这个问题有意义的唯一上下文,似乎可能在nodejs中),并假设NetworkUntils.checkIfReachable()返回一个promise或者可以很容易地更改为返回一个promise ,那么你可以做到以下几点:

findFirstReachableServer(ipAddresses) {
    if (!ipAddresses || !ipAddresses.length) {
        return Promise.reject(new Error("No servers ips provided"));
    }
    let agentOptions = {...};
    let index = 0;
    function next() {
        if (index < ipAddresses.length) {
            let ipAddress = ipAddresses[index++];
            return NetworkUtils.checkIfReachable(agentOptions, ipAddress).then(function(isReachable) {
                if (!isReachable) {
                    return next();
                } else {
                    return ipAddress;
                }
            })
        } else {
            return new Error("No working servers found");
        }
    }
    return Promise.resolve().then(next);
}

此函数返回一个使用ipAddress解析的promise,如果找到了可到达的promise。如果没有传入任何地址,找不到可到达的地址,或者NetworkUtils.checkIfReachable()因任何内部原因拒绝,则拒绝。

注意,要按顺序运行非阻塞异步操作,您不能使用普通for循环,因为每个单独的操作都不会阻止,因此for循环赢了&# 39;等待它们(它将在任何操作完成之前运行完成)。因此,您必须使用不同的排序方法。有很多不同的方法可以做到这一点。由于您不一定要运行整个序列,因此我选择了手动排序,您可以控制是否调用下一次迭代。

答案 1 :(得分:0)

鉴于你标记了问题,使用它确实不是一个坏主意:

async function findWorkingServer(ipAddresses) {
    if (ipAddresses.length > 0) {
        for (const currentServer of ipAddresses) {
            const agentOptions = { … };
            const isReachable = await NetworkUtils.checkIfReachable(agentOptions, ip);
//          We do "block" here  ^^^^^
            if (isReachable) {
                return currentServer;
            }
        }
        throw new Error("No working servers found");
    } else {
        return new Error("No servers ips provided"); // I think you meant to `throw` here
    }
}