以下代码两次输出端口号40001,然后错误退出:
Error: listen EADDRINUSE
我相信这是因为代码是异步的,并且在分配另一个端口之前不会等待foreach循环的整个迭代。
我应该使用哪个Node惯用法来解决这个问题?我想遍历数组,并在每次迭代的不同端口上建立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被发现两次。
因此,这里有2种方法。您可以使用延续,即创建下一步以执行功能,然后在占用端口后调用延续。
在这种情况下,仅跟踪端口可能会更容易。首先在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();
});
});
});
});
});
});
使用continuable-series的延续(未经测试,但应该可以给您一个思路)
var phantom = require("phantom")
var portscanner = require("portscanner")
var series = require("continuable-series");
module.exports = function processPosts(posts) {
var callInSeries = posts.map(function (post) {
return phantomPage.bind(null, post)
});
series(callInSeries, function (err) {
if (err) {
console.log(err)
}
}
}
function phantomPage(post, callback) {
portscanner.findAPortNotInUse(40000, 60000, 'localhost', function(err, freeport) {
if (err) {
return callback(err);
}
phantom.create({'port': freeport}, function(ph){
// Now that we have opened the port, we can callback immediately
// starting the next iteration
callback(null)
return ph.createPage(function(page) {
return page.open("http://www.target.com/showthread.php?t="+post.post_id, function(status) {
console.log("opened post? ", status);
return page.get('plainText', function(content){
console.log(content);
return ph.exit();
});
});
});
});
});
}