Skip to content

事件循环 ​

qzjs 在自己的内部线程上拥有一个事件循环(libuv)。

谁在运行循环 ​

qz_create 启动一个专用内部线程(uv_thread_t),该线程运行一个 libuv 循环(嵌入式在运行时中的 uv_loop_t)。该循环驱动所有异步工作 — HTTP、文件 I/O、定时器 — 且所有 JS 都在同一线程上运行,因此 Promise 微任务在循环迭代之间自然排空。宿主线程从不触碰循环。

宿主如何驱动工作 ​

宿主不能求值,也不 tick。它通过发送 JSON 消息并接收回复来驱动运行时:

c
#include <qzjs/qzjs.h>
#include <stdio.h>

static void on_message(qz_t *rt, const char *json, size_t len, void *data) {
    (void)rt; (void)data;
    printf("received: %.*s\n", (int)len, json);
}

int main(void) {
    qz_config_t cfg = {0};
    cfg.initial_script =
        "globalThis.onmessage = function (e) { postMessage('pong'); };";
    cfg.message_cb = on_message;
    qz_t *rt = qz_create(&cfg);
    if (!rt) return 1;

    qz_post_message(rt, "{\"cmd\":\"ping\"}", 14);
    // on_message 在回复就绪时于 qzjs 线程上触发。
    // 宿主同时可以自由做自己的工作 — 从不被 qzjs 阻塞。

    qz_destroy(rt);
    return 0;
}

qz_post_message 是线程安全的(JSON 会被拷贝),因此可以从任何线程调用。message_cb 在 qzjs 线程上触发 — 你的回调必须线程安全。

为什么这样设计 ​

  • qzjs 自驱运行,宿主线程保持自由去做自己的工作。
  • 所有异步事件和 JS 回调在 qzjs 单一内部线程上串行化 — 运行时内部无锁、无竞争。
  • 微任务在循环迭代之间自动排空。

MIT 许可证