Как сохранить обратный вызов на потом с помощью node-addon-api?

Я хочу, чтобы моя библиотека C могла вызывать функцию JS несколько раз. Я заставил его работать с помощью Nan, но у меня возникли проблемы с преобразованием его в N-API/node-addon-api.

Как сохранить функцию обратного вызова JS и вызвать ее позже из C?

Вот что у меня есть с помощью Nan:

Persistent<Function> r_log;
void sendLogMessageToJS(char* msg) {
    if (!r_log.IsEmpty()) {
        Isolate* isolate = Isolate::GetCurrent();
        Local<Function> func = Local<Function>::New(isolate, r_log);
        if (!func.IsEmpty()) {
        const unsigned argc = 1;
        Local<Value> argv[argc] = {
            String::NewFromUtf8(isolate, msg)
        };
        func->Call(Null(isolate), argc, argv);
        }
    }
}
NAN_METHOD(register_logger) {
    Isolate* isolate = info.GetIsolate();
    if (info[0]->IsFunction()) {
        Local<Function> func = Local<Function>::Cast(info[0]);
        Function * ptr = *func;
        r_log.Reset(isolate, func);
        myclibrary_register_logger(sendLogMessageToJS);
    } else {
        r_log.Reset();
    }
}

Как сделать то же самое с node-addon-api? Все примеры, которые я видел, немедленно вызывают обратный вызов или используют AsyncWorker, чтобы каким-то образом сохранить обратный вызов. Я не могу понять, как это делает AsyncWorker.


person iffy    schedule 21.01.2019    source источник
comment
Вы говорите о библиотеке C, поэтому я думаю, что вы имеете в виду использование N-API, а не ее оболочки C++node-addon-api.   -  person Evgeniy Berezovsky    schedule 29.01.2019


Ответы (1)


Я получил ответ от сопровождающих node-addon-api, который привел меня к этому решению:

FunctionReference r_log;
void emitLogInJS(char* msg) {
  if (r_log != nullptr) {
    const Env env = r_log.Env();
    const String message = String::New(env, msg);
    const std::vector<napi_value> args = {message}; 
    r_log.Call(args);
  } 
}
void register_logger(const CallbackInfo& info) {
  r_log = Persistent(info[0].As<Function>());
  myclibrary_register_logger(emitLogInJS);
}
person iffy    schedule 29.01.2019
comment
У вас не происходит сбой с # Fatal error in HandleScope::HandleScope / # Entering the V8 API without proper locking in place при выполнении r_log.Call(args) из другого потока? - person Evgeniy Berezovsky; 08.02.2019
comment
@EugeneBeresovsky Я недостаточно знаком с Node/N-API/C, чтобы знать, вызываю ли я его из другого потока или нет. Я ничего явно не делаю с потоками в моем коде C/C++ или в моем JS. Все вызовы emitLogInJS изначально вызваны синхронными вызовами JS к моему синхронному коду C. Я ничего не делаю асинхронно. - person iffy; 08.02.2019
comment
Привет @EugeneBeresovsk, не могли бы вы проверить github.com/nodejs/node-addon-api /вопросы/947 - person Vijay Kumbhani; 23.03.2021