改进了从Promise内部的WebSocket获取onmessage事件的结果



我有一个WebSocket客户端,它发送一条消息,然后接收一个响应。我希望能够在任何地方调用它,并将响应存储回来,就像这样:

// Global var
var response
// Connection to WS
connect = () => {
return new Promise(function(resolve, reject) {
var server = new WebSocket('ws://localhost:8443/test/');
server.onopen = function() {
resolve(server);
};
server.onerror = function(err) {
console.log(err)
reject(err);
};
});
}
// Send request and receive message back
async request(data){
var request = {
id: "test",
data: data
}
connect().then((server) => {          
server.send(JSON.stringify(request))
server.onmessage = ({data}) => {
response = JSON.parse(data) // save result
}
})
.catch(function(err) {
console.log(err)
});
}
// Make request
await request("test")

// Access response
console.log(response) // prints undefined

最终,响应仍然是未定义的,因为当它到达console.log(response)时,还没有从异步调用中更新。

我能想到的唯一解决方案是添加这样的延迟:

delay(){
var promise = new Promise(function(resolve) {
window.setTimeout(function() {
resolve('done!');
}, 10);
});
return promise;
}
// Make request
await request("test")
// Await for delay 
await delay();

// Access response
console.log(response) // prints data received!

这是正确的方法吗?似乎很奇怪,增加10ms的延迟就足以让它更新。如果你有比我添加的延迟更好的解决方案,请告诉我。

您的connect()调用前面缺少await。除此之外,您永远不会告诉您的承诺等待响应本身。这里有一个快速解决方案。

await connect().then((server) => {          
server.send(JSON.stringify(request))
return new Promise((resolve, reject) => {
server.onmessage = ({data}) => {
response = JSON.parse(data) // save result
resolve()
}
})
})

从技术上讲,您可以将await替换为return,因为这是您的结束语句,并且您已经在request调用中放置了await

return connect().then((server) => {          
server.send(JSON.stringify(request))
return new Promise((resolve, reject) => {
server.onmessage = ({data}) => {
response = JSON.parse(data) // save result
resolve()
}
})
})

尽管它是有效的,但我鼓励您重构连接初始化过程——绝对没有理由在每次请求尝试时都重新连接到WS,除非您在请求完成时确实断开了与WS的连接。

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

相关内容

  • 没有找到相关文章

最新更新