问题描述
我有一个代码,但是它的问题是 function getip()
没有先执行。我没有用 Javascript 编写太多代码,所以我真的不知道发生了什么。我希望在 console.log('connected!')
完全完成后执行 function getip()
。
如果可能的话,如果有人能够进行必要的更改并提供一些简短的解释,我将不胜感激。
(async function getip() {
var responses = [];
var ips = [ "IP1","IP2" ]
var length = ips.length
for (var i = 0; i < length; i++) {
(async function() {
var ws = new WebSocket('ws://' + ips[i] + ':80');
await new Promise(function(res) {
var timeout = setTimeout(function() {
console.log("Socket connection timeout",ws.readyState);
console.log(ws.url);
if (ws.readyState == 3){
responses.push('connected')
} else {
responses.push('not connected')
}
ws.close();
},5000);
});
})();
}
})();
console.log('connected!')
解决方法
发生了一些事情:
getip
函数是异步的,这意味着它在执行时不会阻止其他代码运行。由于异步性质,这会导致调用 console.log('connected')
。
您的 Promise
不会在任何地方调用 res
。这意味着承诺永远不会解决,因此,您的 await
永远不会停止等待。
在您的承诺的 setTimeout
中,您正在寻找网络套接字实例上的 readyState
。目前您正在检查的是该状态是否为 3
,这意味着关闭,它(可能)不是,因为您刚刚打开了网络套接字。相反,关闭连接并拒绝承诺,说承诺失败。
使用 onopen
和 onerror
事件来监控网络套接字是否已成功打开或何时发生错误。在 onopen
函数中调用 resolve
以成功关闭承诺。在 onerror
回调 reject
中,promise 并将一些数据传递给它,以便您可以读取错误日志。在这两种情况下,清除超时。
不是对每个 await
进行 Promise
-ing,而是将它们全部收集在一个数组中,并使用 Promise.all()
来等待承诺数组。这将确保所有 Web 套接字并行打开。当一切顺利时,console.log('connected')
将登录到控制台。否则,如果其中一个承诺产生了错误,它将记录一个错误。
这个主题很难掌握,需要一些练习才能获得点击时刻。
以下示例使用了上述所有做法。检查它,如果您有任何后续问题,请随时提出。
async function getip() {
const ips = ["IP1","IP2"];
const responses = ips.map(ip => new Promise((resolve,reject) => {
const ws = new WebSocket(`ws://${ip}:80`);
let timeout = setTimeout(() => {
// Save the state before closing,otherwise it will always be the closed state.
const currentState = ws.readyState;
ws.close();
reject({
message: 'Socket connection timeout',state: currentState
});
},5000);
ws.onopen = () => {
clearTimeout(timeout);
resolve(ws);
};
ws.onerror = event => {
clearTimeout(timeout);
reject({
message: 'Socket connection error',event
});
};
}));
const sockets = await Promise.all(responses);
return sockets;
}
getip().then(sockets => {
console.log('connected!',sockets);
}).catch(error => {
console.log(error);
});