改进从 Promise 中的 WebSocket 获取 onmessage 事件的结果
Improve getting result from onmessage event from WebSocket inside Promise
我有一个 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!
这是正确的方法吗?添加 10 毫秒的延迟足以让它更新似乎很奇怪。如果您有比我添加的延迟更好的解决方案,请告诉我。
你的 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
,因为这是您的结束语,并且您已将 await
置于 request
通话中。
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,除非您在它完成时实际断开连接。
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await
我有一个 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!
这是正确的方法吗?添加 10 毫秒的延迟足以让它更新似乎很奇怪。如果您有比我添加的延迟更好的解决方案,请告诉我。
你的 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
,因为这是您的结束语,并且您已将 await
置于 request
通话中。
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,除非您在它完成时实际断开连接。
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await