Asynchronous Code¶
Emscripten supports two ways (Asyncify and JSPI) that let synchronous C or C++ code interact with asynchronous JavaScript. This allows things like:
A synchronous call in C that yields to the event loop, which allows browser events to be handled.
A synchronous call in C that waits for an asynchronous operation in JS to complete.
In general the two options are very similar, but rely on different underlying mechanisms to work.
Asyncify - Asyncify automatically transforms your compiled code into a form that can be paused and resumed, and handles pausing and resuming for you, so that it is asynchronous (hence the name “Asyncify”) even though you wrote it in a normal synchronous way. This works in most environments, but can cause the Wasm output to be much larger.
JSPI - Uses the VM’s support for JavaScript Promise Integration (JSPI) for interacting with async JavaScript. The code size will remain the same.
For more on Asyncify see the Asyncify introduction blogpost for general background and details of how it works internally (you can also view this talk about Asyncify). The following expands on the Emscripten examples from that post.
Sleeping / yielding to the event loop¶
Let’s begin with the example from that blogpost:
// example.cpp
#include <emscripten.h>
#include <stdio.h>
// start_timer(): call JS to set an async timer for 500ms
EM_JS(void, start_timer, (), {
Module.timer = false;
setTimeout(function() {
Module.timer = true;
}, 500);
});
// check_timer(): check if that timer occurred
EM_JS(bool, check_timer, (), {
return Module.timer;
});