我有一个用JavaScript编写的函数,无法修改:
function doSomething() {
doFirst();
(...)
}
doSomething内部的第一个函数通过WebSocket发送一个数据包,并且必须等待响应才能返回。因此,换句话说,我需要doFirst在执行(...)之前等待此响应。
首先想到的是,我认为可以在doFirst完成后使用回调函数来调用(...),但是我不能这样做,因为我无法在doSomething上写任何东西,因此以下示例完全不可能:
function doSomething() {
doFirst(function() {
(...)
});
}
因此,在这种限制下,我必须能够在doFirst内编写一些内容(但要再次声明,不是doSomething)以实现此行为。
如果我只声明WebSocket的onmessage回调,则(...)在套接字获得响应之前完成,并且如果我使用类似以下内容的话:
while(!received) { }
当然,浏览器会挂起,即使我得到响应,也无法继续。
答案 0 :(得分:1)
轮询,就像您的while(!received)
一样,但是有一个睡眠,因此eventloop允许之间有其他指令。即:
const checkInterval = setInterval(function(){
if(!received) return;
clearInterval(checkInterval);
//do your stuff here
}, 10)
答案 1 :(得分:0)
我认为使用flag
的传统解决方案会很有用。您可以在flag=False
或doSomething()
之外初始化变量doFirst()
,并在得到响应时将其设为flag=True
。
答案 2 :(得分:0)
还有另一种“可能的”方法,这是一种基于Promise的方法,该方法仍然依赖于间隔,但是隔离了其余的代码。
var _onceReceived = function(timeoutSeverity) {
return new Promise(function(resolve, reject){
var _mInterval = setInterval(function(){
if (received !== null && received !== undefined) {
clearInterval(_mInterval);
resolve(received);
}
}, timeoutSeverity);
});
}
基本上,这将查找收到的变量并检查其是否有效,从而使您可以根据所需的严重性设置自定义超时。
样品用量:
_onceReceived(1000).then(function(res){
alert('received was now set, and it is: ' + res);
});
完整样本:
var received;
function doesSomething() {
setTimeout(function(){
received = 10;
}, 5000);
}
var _onceReceived = function(timeoutSeverity) {
return new Promise(function(resolve, reject){
var _mInterval = setInterval(function(){
console.log('checking!');
if (received !== null && received !== undefined) {
clearInterval(_mInterval);
resolve(received);
}
}, timeoutSeverity);
});
}
doesSomething();
_onceReceived(1000).then(function(res){
alert('received was now set, and it is: ' + res);
});
答案 3 :(得分:0)
您可以通过基于承诺和等待操作员的操作来完成此操作。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
function doFirst() {
return new Promise(resolve => {
setTimeout(() => {
resolve('do first');
}, 2000);
});
}
async function doSomething() {
var received = await doFirst();
console.log(received);
}