【发布时间】:2018-08-20 18:28:01
【问题描述】:
我在 $http.get 调用中有一个很长的承诺链,需要几分钟才能完成。需要很长时间的部分是一个 for 循环,它遍历 160 个数组元素并运行一长串套接字连接测试。然而,在 for 循环的第 84 次迭代前后,整个 Promise 链(或者可能是 get 调用)重新开始。而另一个仍在运行。然后,一旦第一个完成, res.send 在新链运行时永远不会通过,这会无限重复。
router.get('/', function(req, res) {
fs.readdir('C:\\Temp\\hostPorts', function(err, files) {
console.log('files', files);
chooseFile(files).then(response => {readTheFile(response).then(async (result) => {
splitText(result).then( async (final) => {
console.log('final version', final);
res.send({file: final});
})
// res.send({file: result});
}).catch(error => {
console.log(error);
}) //end catch
}); //end promise
}); //end read
}); //end get
这是我的调用,splitText 函数是它卡住的地方。我将在下面发布 splitText 函数的源代码,但我确信它以某种方式创建了两个实例,因为每次在第 84 次迭代时,我的终端控制台都会重新打印初始 console.log('files', files) 然后运行另一个链中的承诺。
它最终会完成第一个,因为 console.log('final version', final) 确实会打印出来。但是 res.send 永远不会发生,第二个承诺链继续运行。然后是第三个,等等。
这是来自长循环的代码
async function splitText(file){
let tableData = "<table border=1 cellspacing=0><tr>";
let splited = file.trim().split(/\s+/);
//vars for checking connectivity
for (let i = 0; i < splited.length; i++) {
console.log(splited[i] + " " + i);
if(i < 4 ) {
tableData += "<th>" + splited[i] + "</th>";
//if its less than 4 print out table headers
}
else if (i == 4){
tableData += "</tr><tr><td>" + splited[i] + "</td>";
//if its 4 create a new row for data
}
else if (i % 3 == 0){
//if modulo 3 is 0 then its on a port, checks connectivity and adds it to the row as data after port
//then starts a new row
let host = splited[(i - 1)]; //1 index ago was host
let port = parseInt(splited[(i)]); //current array index is port
console.log('host: ' + host );
console.log('port: ' + port );
await testPort(port, host).then(async (reachable) => {
console.log(reachable);
if (reachable) {
tableData += "<td>" + splited[i] + "</td><td>" + "<font color=\"GREEN\">UP</font>" + "</tr><tr>";
}
else {
tableData += "<td>" + splited[i] + "</td><td>" + "<font color=\"RED\">DOWN</font>" + "</tr><tr>";
}
});
} //end else if
else {
tableData += "<td>" + splited[i] + "</td>";
//otherwise adds tabledata
}
} //end for
return tableData;
} //end function
这是检查主机/端口是否启动的异步函数。
async function testPort(port, host){
return new Promise(resolve => {
const socket = new net.Socket();
const onError = () => {
socket.destroy();
resolve(false);
};
socket.setTimeout(10000);
socket.on('error', onError);
socket.on('timeout', onError);
socket.connect(port, host, () => {
socket.end();
resolve(true);
}); //end promise
});
我不确定这是否是 HTTP 的问题。在花费太长时间后重新启动,但是我将超时设置为 5 分钟。或者,如果这是在没有得到响应后重新启动的承诺链。但我真的很想知道这一点,因为无论哪种方式,我都不会将数据返回给我的客户,而且据我所知,我从来没有回忆过一个函数或创建了一个无限循环。
【问题讨论】:
-
添加更多日志以找出究竟是什么重复。
-
你真的应该学习一下 Promise 是如何工作的,以及
await和async的含义是什么。您的路由中没有正确链接 Promise,因此您无法记录这些 Promise 中发生的任何错误,并且asnyc没有用处。 -
你能放一个你的主机端口文件的样本(至少像 10-15 列空间分隔符)吗?不清楚“i == 4”列(第一数据行中的第一列)如何处理第二列......
-
其他由模 3 处理。直到第一行之后我才开始在那里处理它们,因为在与端口/主机相反的表头上运行我在 else 模 3 中的代码会返回错误
标签: javascript node.js promise async-await angular-http