gpt4 book ai didi

javascript - 运行服务器时 Promise.all() 无法解析 - 否则工作正常

转载 作者:IT老高 更新时间:2023-10-28 23:25:20 25 4
gpt4 key购买 nike

我编写了一个小工具,它在调用其他几个 Promise 后返回一个 Promise。这个工具在我单独测试时效果很好,在下面的示例中大约需要 10 秒。但是,当我尝试将它与 http 服务器实例一起运行时,它需要几分钟才能返回,如果有的话!

我很确定我只是在这里误解了一些东西,因为我对 Node.js 不是非常精通。如果有人能发现问题,或提出使用 Promise 处理异步方法的替代方法,请告诉我!

澄清一下,挂起的是 traceRoute 函数返回的 Promise.all。子 promise 都按预期解决。

编辑: 正如评论中所建议的,我还尝试了一个不调用 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) )

下面是从服务器实例内部调用的相同逻辑,这是不工作。请参阅内联注释以了解它的具体挂起位置。

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);

注意:我尝试在 server.listen 之前,server.listen 之后,从 wss.on 内部调用它('connection', ...。没有任何区别。在服务器监听时在任何地方调用它,会导致它以不确定的方式运行。

最佳答案

我不会接受这个答案,因为它只是一种解决方法;评论太长了……

包括 Promise.all 在内的所有 promise 都不会引发异常。但是,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)
});

关于javascript - 运行服务器时 Promise.all() 无法解析 - 否则工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45510059/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com