Javascript 如何确保该循环在node.js中按预期运行

Javascript 如何确保该循环在node.js中按预期运行,javascript,node.js,Javascript,Node.js,以下代码输出端口号40001两次,然后返回错误: Error: listen EADDRINUSE 我相信这是因为代码是异步的,在分配另一个端口之前,不会等待foreach循环的整个迭代 我应该使用哪个节点习惯用法来解决这个问题?我想在一个数组上循环,并在每次迭代中在不同的端口上建立phantomJS连接 posts.forEach(function(element, index, posts){ portscanner.findAPortNotInUse(40000, 60

以下代码输出端口号40001两次,然后返回错误:

Error: listen EADDRINUSE
我相信这是因为代码是异步的,在分配另一个端口之前,不会等待foreach循环的整个迭代

我应该使用哪个节点习惯用法来解决这个问题?我想在一个数组上循环,并在每次迭代中在不同的端口上建立phantomJS连接

posts.forEach(function(element, index, posts){

        portscanner.findAPortNotInUse(40000, 60000, 'localhost', function(err, freeport) {
        if(err) {
            console.log(err);
        }
            console.log(freeport); //outputs 40001 twice then exits
            phantom.create({'port': freeport}, function(ph){

                return ph.createPage(function(page) {
                    return page.open("http://www.target.com/showthread.php?t="+posts[index].post_id, function(status) {
                        console.log("opened post? ", status);

                        return page.get('plainText', function(content){
                            console.log(content);
                            return ph.exit();
                        });
                    });
                });
            });
        });
    });

所以你是对的。这里的问题是,当您在第一次迭代(40001)中找到端口时,您不会在下一次迭代之前使用它,因此40001会被找到两次

这里有两种方法。要么使用延续,即创建下一步作为函数执行,然后在使用端口后调用延续

在这种情况下,只跟踪端口可能更容易。首先将基本端口定义为40000,当您找到一个端口时,将基本端口设置为
freeport+1
,并在该范围内搜索

var startPort = 40000
var endPort = 60000

posts.forEach(function(element, index, posts){

    portscanner.findAPortNotInUse(startPort, endPort, 'localhost', function(err, freeport) {
        if(err) {
            return console.log(err);
        }
        console.log(freeport);

        startPort = freeport + 1 // correct the start port to search from

        phantom.create({'port': freeport}, function(ph){

            return ph.createPage(function(page) {
                return page.open("http://www.target.com/showthread.php?t="+posts[index].post_id, function(status) {
                    console.log("opened post? ", status);

                    return page.get('plainText', function(content){
                        console.log(content);
                        return ph.exit();
                    });
                });
            });
        });
    });
});
使用可连续系列继续(未经测试,但会给您一个想法)


所以你是对的。这里的问题是,当您在第一次迭代(40001)中找到端口时,您不会在下一次迭代之前使用它,因此40001会被找到两次

这里有两种方法。要么使用延续,即创建下一步作为函数执行,然后在使用端口后调用延续

在这种情况下,只跟踪端口可能更容易。首先将基本端口定义为40000,当您找到一个端口时,将基本端口设置为
freeport+1
,并在该范围内搜索

var startPort = 40000
var endPort = 60000

posts.forEach(function(element, index, posts){

    portscanner.findAPortNotInUse(startPort, endPort, 'localhost', function(err, freeport) {
        if(err) {
            return console.log(err);
        }
        console.log(freeport);

        startPort = freeport + 1 // correct the start port to search from

        phantom.create({'port': freeport}, function(ph){

            return ph.createPage(function(page) {
                return page.open("http://www.target.com/showthread.php?t="+posts[index].post_id, function(status) {
                    console.log("opened post? ", status);

                    return page.get('plainText', function(content){
                        console.log(content);
                        return ph.exit();
                    });
                });
            });
        });
    });
});
使用可连续系列继续(未经测试,但会给您一个想法)


我最近遇到了同样的问题,并通过使用Math.Random生成一个开始端口值来修复它,然后添加500来获得结束端口值

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
}

var startPort = getRandomInt(3000, 8000);
var endPort = startPort + 500;

portscan.findAPortNotInUse(startPort, endPort, '127.0.0.1', function (err, ports) {
   .....
}

我最近遇到了同样的问题,并通过使用Math.Random生成一个开始端口值来修复它,然后添加500来获得结束端口值

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
}

var startPort = getRandomInt(3000, 8000);
var endPort = startPort + 500;

portscan.findAPortNotInUse(startPort, endPort, '127.0.0.1', function (err, ports) {
   .....
}

谢谢其他人也建议使用“异步串行”或process.nextTick()。对此有什么想法吗?这种方法有一些警告。延续会随着时间的推移表现得更好,但这会对搜索0个端口的范围造成影响。process.nextTick无法解决问题,因为phantom到startAsync serial可能需要任意数量的时间才能解决问题。手动延续与异步串行方法相同。我可以添加它作为一个例子。我添加了一个基于“连续系列”模块的例子。这只是一种风格/复杂性偏好。谢谢!其他人也建议使用“异步串行”或process.nextTick()。对此有什么想法吗?这种方法有一些警告。延续会随着时间的推移表现得更好,但这会对搜索0个端口的范围造成影响。process.nextTick无法解决问题,因为phantom到startAsync serial可能需要任意数量的时间才能解决问题。手动延续与异步串行方法相同。我可以添加它作为一个例子。我添加了一个基于“连续系列”模块的例子。这只是一种风格/复杂性偏好。