【问题标题】:how to implement node-nan callback using node-addon-api如何使用 node-addon-api 实现 node-nan 回调
【发布时间】:2020-01-23 00:22:56
【问题描述】:

到目前为止,我只实现了同步 node-addon-api 方法,即 JavaScript 函数进行调用,工作完成,然后插件返回。我对 v8、libuv 和 node 的内部工作有很大的了解,所以请纠正任何明显的误解。

目标是在从 v8 调用 C++ 垃圾回收回调时调用 JavaScript 回调。我最初只是从 v8 垃圾收集回调中调用了 JavaScript 回调,但在几次调用后最终得到了一个 segv。似乎只是在从 v8 回调调用时调用 JavaScript 有一些问题(v8 文档回调不应该分配对象)。于是我环顾四周,发现了一个基于 Nan 的示例,它使用 libuv 和 Nan 的 AsyncResource 进行回调。以下方法使用node-nan

NAN_GC_CALLBACK(afterGC) {
    uint64_t et = uv_hrtime() - gcStartTime;

    // other bookkeeping for GCData_t raw.

    if (doCallbacks) {
        uv_async_t* async = new uv_async_t;
        GCData_t* data = new GCData_t;

        *data = raw;
        data->gcTime = et;

        async->data = data;

        uv_async_init(uv_default_loop(), async, asyncCB);
        uv_async_send(async);
    }
}

class GCResponseResource : public Nan::AsyncResource {
 public:
    GCResponseResource(Local<Function> callback_)
        : Nan::AsyncResource("nan:gcstats.DeferredCallback") {
    callback.Reset(callback_);
    }

    ~GCResponseResource() {
        callback.Reset();
    }

    Nan::Persistent<Function> callback;
};

static GCResponseResource* asyncResource;

static void closeCB(uv_handle_t *handle) {
    delete handle;
}

static void asyncCB(uv_async_t *handle) {
    Nan::HandleScope scope;
    GCData_t* data = static_cast<GCData_t*>(handle->data);

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New("gcCount").ToLocalChecked(),
        Nan::New<Number>((data->gcCount));
    Nan::Set(obj, Nan::New("gcTime").ToLocalChecked(),
        Nan::New<Number>(data->gcTime));

    Local<Object> counts = Nan::New<v8::Object>();
    for (int i = 0; i < maxTypeCount; i++) {
        if (data->typeCounts[i] != 0) {
            Nan::Set(counts, i, Nan::New<Number>(data->typeCounts[i]));
        }
    }
    Nan::Set(obj, Nan::New("gcTypeCounts").ToLocalChecked(), counts);

    Local<Value> arguments[] = {obj};
    Local<Function> callback = Nan::New(asyncResource->callback);
    v8::Local<v8::Object> target = Nan::New<v8::Object>();
    asyncResource->runInAsyncScope(target, callback, 1, arguments);
    delete data;
    uv_close((uv_handle_t*) handle, closeCB);
}

我的问题是如何使用 node-addon-api 而不是 nan 来做到这一点?

我不清楚 uv_async_inituv_async_send 等的 node-addon-api 等价物是什么。这部分是因为我不清楚需要哪些底层 N-API(而不是 node-addon-api)函数。

我一直找不到这样的例子。 callback example 是完全同步的。 async pi example 使用工作线程来执行任务,但与使用 uv 原语的基于 nan 的代码中的方法相比,这似乎有点矫枉过正。

【问题讨论】:

    标签: c++ node.js libuv node-addon-api node-nan


    【解决方案1】:

    您的示例并不是真正的异步,因为 GC 回调在主线程中运行。然而,当 JS 世界因为 GC 停止时,这并不意味着它以允许回调运行的方式停止 - 因为 GC 可以在函数中间停止它。

    您需要ThreadSafeFunction 来执行此操作。看这里的例子: https://github.com/nodejs/node-addon-api/blob/main/doc/threadsafe_function.md

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-15
      • 2019-06-21
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-21
      相关资源
      最近更新 更多