You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Emscripten/embind在C++中以await方式调用JS异步函数

在Emscripten 1.38.31中实现JS异步函数的"await"式调用

由于Emscripten运行在浏览器主线程(或Worker)环境中,无法直接实现类似JS的同步await(会阻塞事件循环导致页面无响应),但可以通过Promise回调绑定的方式模拟异步等待效果,以下是具体实现方案:

核心思路

JS的async函数本质返回Promise,我们可以在C中调用该函数后,给返回的Promise绑定then回调,当Promise resolve时触发C的处理逻辑。

方案一:直接绑定Promise回调

#include <emscripten.h>
#include <emscripten/val.h>
#include <string>

using namespace emscripten;

emscripten::val func2;

// 处理JS异步函数返回结果的C++回调
void handle_get_data_result(emscripten::val result) {
    std::string data = result.as<std::string>();
    // 此处编写拿到数据后的业务逻辑
    printf("JS异步函数返回数据:%s\n", data.c_str());
}

void set_js_func(emscripten::val func) {
    func2 = func;

    // 调用JS异步函数,并为返回的Promise绑定then回调
    func2().call<void>("then", emscripten::val::module_property("handle_get_data_result"));
}

// 绑定C++函数到JS环境
EMSCRIPTEN_BINDINGS(my_module) {
    emscripten::function("setJSFunction", &set_js_func);
    emscripten::function("handle_get_data_result", &handle_get_data_result);
}

方案二:封装异步调用逻辑(贴近await使用体验)

如果需要多次调用异步函数并在拿到结果后执行后续逻辑,可以封装一个异步调用函数,通过回调传递结果:

#include <emscripten.h>
#include <emscripten/val.h>
#include <string>
#include <functional>

using namespace emscripten;

emscripten::val func2;
std::function<void(std::string)> pending_callback;

void handle_get_data_result(emscripten::val result) {
    std::string data = result.as<std::string>();
    if (pending_callback) {
        // 触发回调,传递异步结果
        pending_callback(data);
        pending_callback = nullptr;
    }
}

// 封装的"await"式调用函数
void await_get_data(std::function<void(std::string)> callback) {
    if (func2.isUndefined()) {
        printf("未设置JS异步函数\n");
        return;
    }
    pending_callback = callback;
    func2().call<void>("then", emscripten::val::module_property("handle_get_data_result"));
}

// 示例:调用封装函数
void demo_usage() {
    await_get_data([](std::string data) {
        printf("获取到异步数据:%s\n", data.c_str());
        // 此处编写原本要在"await"之后执行的逻辑
    });
}

EMSCRIPTEN_BINDINGS(my_module) {
    emscripten::function("setJSFunction", &set_js_func);
    emscripten::function("handle_get_data_result", &handle_get_data_result);
    emscripten::function("demoUsage", &demo_usage); // 可选:暴露给JS调用示例
}

关键注意事项

  1. 禁止同步阻塞:不要尝试在C++中同步等待Promise结果,这会卡死浏览器主线程,所有异步逻辑必须基于回调实现。
  2. 函数绑定要求:用于处理结果的C++回调必须通过EMSCRIPTEN_BINDINGS暴露给JS环境,否则无法被Promise的then方法调用。
  3. 版本兼容性:该方案完全适配Emscripten 1.38.31,无需依赖高版本特性。

内容的提问来源于stack exchange,提问作者user558185

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:46:17