Node.js 如何有条件地处理带有承诺的for循环

Node.js 如何有条件地处理带有承诺的for循环,node.js,asynchronous,ecmascript-6,promise,async-await,Node.js,Asynchronous,Ecmascript 6,Promise,Async Await,我仍在试图找到一种方法,有条件地处理循环中的承诺,并能够打破循环 下面是一个简短的例子 return new Promise(function (resolve, reject) { if (ipAddresses.length > 0) { let currentServer, agentOptions; for (let i = 0; i < i

我仍在试图找到一种方法,有条件地处理循环中的承诺,并能够打破循环

下面是一个简短的例子

return 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"));
                    }
                })
返回新承诺(函数(解析、拒绝){
如果(ipAddresses.length>0){
让currentServer、agentOptions;
for(设i=0;i
问题是,我不需要并行运行所有请求,即
Promise.all
async.foreach
,但我需要依次调用每个Promise,如果条件为真,我需要打破循环,只要找到了可访问的服务器,就不要再发出任何请求

请建议处理此用例的正确方法。我已经寻找了很长时间,但仍然没有找到任何好的解决方案

谢谢

编辑


抱歉,是的
NetworkUntils.checkIfReachable()
返回promise

假设
NetworkUntils.checkIfReachable()
实际上是异步的(这是这个问题在nodejs中有意义的唯一上下文),并假设
NetworkUntils.checkIfReachable()
返回承诺或可以轻松更改以返回承诺,然后您可以执行以下操作:

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);
}
findFirstReachableServer(IP地址){
如果(!IPAddresss | |!IPAddresss.length){
返回承诺。拒绝(新错误(“未提供服务器IP”);
}
让agentOptions={…};
设指数=0;
函数next(){
if(索引
此函数返回一个承诺,如果找到可访问的承诺,则该承诺将与ipAddress解析。如果未传入地址,未找到可访问地址,或者
NetworkUtils.checkIfReachable()
因任何内部原因拒绝,则会拒绝


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

假设
NetworkUntils.checkIfReachable()
实际上是异步的(这是这个问题唯一有意义的上下文,并且在nodejs中似乎很可能)假设
NetworkUntils.checkIfReachable()
返回一个承诺,或者可以很容易地更改为返回一个承诺,那么您可以执行以下操作:

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);
}
findFirstReachableServer(IP地址){
如果(!IPAddresss | |!IPAddresss.length){
返回承诺。拒绝(新错误(“未提供服务器IP”);
}
让agentOptions={…};
设指数=0;
函数next(){
if(索引
此函数返回一个承诺,如果找到可访问的承诺,则该承诺将与ipAddress解析。如果未传入地址,未找到可访问地址,或者
NetworkUtils.checkIfReachable()
因任何内部原因拒绝,则会拒绝


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

如果您标记了问题,那么使用它确实是一个不错的主意:

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
    }
}

鉴于您对问题进行了标记,使用该选项确实不是一个坏主意:

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
    }
}

NetworkUtils.checkIfReachable(agentOptions,ip)
是同步请求吗?我想是什么