Ric*_*unn 9 javascript node.js promise
我写了一个小工具,在调用其他几个promises后返回一个promise.当我单独测试它时,这个工具很有用,在下面的例子中大约需要10秒.但是,当我尝试将它与http服务器实例一起运行时,如果有的话,需要几分钟才能返回!
我很确定我只是误解了一些东西,因为我不是非常精通Node.如果有人能够发现问题,或建议使用promises来替代处理异步方法,请告诉我们!
只是为了澄清,这是Promise.all通过返回的traceroute这是挂功能.子承诺都按预期解决.
编辑:正如评论中所建议的那样,我也尝试了一个没有调用Promise.all的递归版本; 同样的问题.
这是一个工作的独立版本,在没有运行任何http服务器实例的情况下调用:
const dns = require('dns');
const ping = require('net-ping');
var traceRoute = (host, ttl, interval, duration) => {
var session = ping.createSession({
ttl:ttl,
timeout: 5000
});
var times = new Array(ttl);
for (var i=0; i<ttl; i++){
times[i] = {'ttl': null, 'ipv4': null, 'hostnames': [], 'times': []}
};
var feedCb = (error, target, ttl, sent, rcvd) => {
var ms = rcvd - sent;
if (error) {
if (error instanceof ping.TimeExceededError) {
times[ttl-1].ttl = ttl;
times[ttl-1].ipv4 = error.source;
times[ttl-1].times.push(ms)
} else {
console.log(target + ": " +
error.toString () +
" (ttl=" + ttl + " ms=" + ms +")");
}
} else {
console.log(target + ": " +
target + " (ttl=" + ttl + " ms=" + ms +")");
}
}
var proms = new Array();
var complete = 0
while(complete < duration){
proms.push(
new Promise((res, rej) => {
setTimeout(function(){
session.traceRoute(
host,
{ maxHopTimeouts: 5 },
feedCb,
function(e,t){
console.log('traceroute done: resolving promise')
res(); // resolve inner promise
}
);
}, complete);
})
)
complete += interval;
}
return Promise.all(proms)
.then(() => {
console.log('resolving traceroute');
return times.filter((t)=> t.ttl != null);
});
}
traceRoute('195.146.144.8', 20, 500, 5000)
.then( (times) => console.log(times) )
Run Code Online (Sandbox Code Playgroud)
下面是从服务器实例内部调用的相同逻辑,这不应该正常工作.请参阅内联注释,了解它的确切位置.
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({server: server, path: "/wss"});
const dns = require('dns');
const ping = require('net-ping');
var traceRoute = (host, ttl, interval, duration) => {
var session = ping.createSession({
ttl:ttl,
timeout: 5000
});
var times = new Array(ttl);
for (var i=0; i<ttl; i++){
times[i] = {'ttl': null, 'ipv4': null, 'hostnames': [], 'times': []}
};
var feedCb = (error, target, ttl, sent, rcvd) => {
var ms = rcvd - sent;
if (error) {
if (error instanceof ping.TimeExceededError) {
times[ttl-1].ttl = ttl;
times[ttl-1].ipv4 = error.source;
times[ttl-1].times.push(ms)
} else {
console.log(target + ": " +
error.toString () + " (ttl=" + ttl + " ms=" + ms +")");
}
} else {
console.log(target + ": " + target +
" (ttl=" + ttl + " ms=" + ms +")");
}
}
var proms = new Array();
var complete = 0
while(complete < duration){
proms.push(
new Promise((res, rej) => {
setTimeout(function(){
session.traceRoute(
host,
{ maxHopTimeouts: 5 },
feedCb,
function(e,t){
console.log('traceroute done: resolving promise')
res(); // resolve inner promise
}
);
}, complete);
})
)
complete += interval;
}
console.log('Promise all:', proms);
// #####################
// Hangs on this promise
// i.e. console.log('resolving traceroute') is not called for several minutes.
// #####################
return Promise.all(proms)
.then(() => {
console.log('resolving traceroute')
return times.filter((t)=> t.ttl != null)
});
}
wss.on('connection', function connection(ws, req) {
traceRoute('195.146.144.8', 20, 500, 5000)
.then((data) => ws.send(data));
});
app.use('/tools/static', express.static('./public/static'));
app.use('/tools/templates', express.static('./public/templates'));
app.get('*', function (req, res) {
res.sendFile(__dirname + '/public/templates/index.html');
});
server.listen(8081);
Run Code Online (Sandbox Code Playgroud)
注意:我试过在之前server.listen,之后server.listen,从内部调用它wss.on('connection', ....这些都没有区别.在服务器正在侦听时,在任何地方调用它会使其以不确定的方式运行.
我不会接受这个答案,因为它只是一种解决方法; 放在评论中的时间太长了......
承诺,包括Promise.all,都没有抛出异常.但是,Node 似乎停止了对Promise.all的调用.我偶然发现,如果我在等待promise.all解析时保持超时循环运行,那么它实际上会在预期时解析.
如果有人能够解释到底发生了什么,我真的很喜欢,因为我不太懂.
var holdDoor = true
var ps = () => {
setTimeout(function(){
console.log('status:', proms);
if (holdDoor) ps();
}, 500);
}
ps();
return Promise.all(proms)
.then(() => {
holdDoor = false
console.log('Resolving all!')
return times.filter((t)=> t.ttl != null)
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
625 次 |
| 最近记录: |