解决等待消息到达



我在JS中有一些websocket代码。我有一个这样的消息处理循环:

socket.addEventListener('message', function (event) {
payload = JSON.parse(event.data)
method = payload.method
// Dispatch messages
if (method == 'cmd1') { 
handle_cmd1(payload);  // trigger event/semaphore here to wait up waiter
}
else if (method == 'cmd2') { ... }
});

在其他地方,我有一个这样的按钮回调:

$('#my-button').change(function() {
handle_button();
});
async function handle_button() {
send_msg('msg1', 'hi');
// wait for server to reply with cmd1
cmd1_data = await something(); // what?
alert(`cmd1 data: $(cmd1_data)`);
}

这个想法是,按钮发送"msg1",服务器应该回复"cmd1"和一些信息。我想等待回复,然后再做一些事情。所以我的问题是如何将这些互锁?在C++中,我会使用信号量。我宁愿不绕圈;Javascript/JQuery中有什么东西可以用来触发然后等待这样的用户定义事件吗?我对JS有点陌生,对JS async/await也很陌生。

编辑:我做了一个简单的jsfiddle来展示我想要的东西。http://jsfiddle.net/xpvt214o/484700/

现在我了解了Javascript中的promise是如何工作的,下面是一个promise的工作示例,它可以通过调用函数从任何地方唤醒:

wakeup = null;
// returns a promise that will be resolved by calling wakeup()
// (could be a list of these or whatever, this is just a simple demo)
function wakeable() {
return new Promise( (resolve) => {
wakeup = () => { resolve(true); }
});
}
// demo of waiting and getting woken up:
async function handle_event() {
while (true) {
console.log("waiting...")
await wakeable(); // returns to event loop here
console.log("handle event woke up!");
}
}
handle_event(); // start in "background"
wakeup(); // wake it up
setTimeout(_ => { wakeup(); }, 500); // wake it up again after a delay

这里发生的情况是,当您调用wakeable()时,它会返回一个promise。该promise是用一个匿名函数(以resolve为arg的函数(构造的;promise构造函数同步调用该函数,并将promise的resolve方法传递给它。在我们的例子中,函数将wakeup设置为另一个调用原始resolve的匿名函数;它是一个闭包,因此即使稍后调用它,它也可以访问解析函数。然后它返回新的承诺。

在这个演示中,我们对这个承诺进行await;将挂起的promise放入队列,保存当前函数状态并返回,就像调用yield的生成器一样。

当调用promise的resolve函数时,它被解析;在这种情况下,调用wakeup()会调用promise的内部resolve((方法,该方法在Javascript事件循环的下一次滴答声中触发任何.then方法(使用上面提到的promise队列(。这里我们使用await,但.then(...)的工作方式与相同

所以没有魔法;I/O和超时承诺的工作方式相同。它们保留了一个函数的私有注册表,以便在I/O事件或超时发生时调用,这些函数调用promise的resolve((,它触发.then()或满足await

顺便说一句,与python中的async不同,在Javascript中,当进程退出时留下一个挂起的promise"打开"是完全可以的,事实上,这个演示做到了这一点。当没有更多的代码可运行时,它就会退出;while循环仍在"等待"这一事实并不能保持进程的运行,因为它实际上只是存储在队列中的一些闭包。事件循环是空的,因此进程退出(假设它在node.js中——在浏览器中,它只是返回等待事件(。

something((应该是一个返回promise((的方法,或者应该是另一个用async表示的方法。

function something(){
return new Promise(resolve,reject) {
//... call your database
// then
resolve(theResult)
// or
reject(theError)
}
}

在大多数情况下,async和wait实际上只是承诺的包装。当promise调用resolve时,wait返回,当promise呼叫reject时抛出异常。

您的async函数可以返回另一个promise;如果它返回另一个值,它就会变成具有该值的已解析承诺。

最新更新