在 Promise 中包装本机 (c++) 方法

Wrap native (c++) method inside a Promise

我有一个执行繁重操作的同步 C++ Node.js 插件函数:

Napi::Object SyncHeavyFunction(const Napi::CallbackInfo& info) {
    std::this_thread::sleep_for(std::chrono::seconds(50));
    ...
    return env.Null();
}

我正在尝试 运行 将其异步包装成 javascript Promise:

console.log("before creating the Promise");
let p = new Promise((resolve) => {
     const out = SyncHeavyFunction();
     reolve(out)
});
console.log("after creating the Promise");

但是,Promise 的创建似乎会阻塞,直到底层本机函数终止。 我想知道这种行为是否是预期的,哪种是仅使用 javascript 代码实现同步本机函数的异步调用的最佳方式。

我最近转型了 gdal-next (https://github.com/yocontra/node-gdal-next) to a completely asynchronous API (https://github.com/mmomtchev/node-gdal-async).

我可能会结束写教程,因为这是一个常见问题。

这远非微不足道,但基本上可以归结为为每个作业创建异步工作程序 (Napi::AsyncWorker),然后在完成时调用 JS 回调。正是这个回调将解析 Promise - 或者一旦你有一个带有回调的函数,你可以简单地使用 util.promisify 到 return a Promise.

您还可以查看 https://github.com/nodejs/node-addon- api/blob/main/doc/async_worker.md 以获取准系统示例:

#include <napi.h>

#include <chrono>
#include <thread>

using namespace Napi;

class EchoWorker : public AsyncWorker {
    public:
        EchoWorker(Function& callback, std::string& echo)
        : AsyncWorker(callback), echo(echo) {}

        ~EchoWorker() {}
    // This code will be executed on the worker thread
    void Execute() override {
        // Need to simulate cpu heavy task
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    void OnOK() override {
        HandleScope scope(Env());
        Callback().Call({Env().Null(), String::New(Env(), echo)});
    }

    private:
        std::string echo;
};
#include <napi.h>

// Include EchoWorker class
// ..

using namespace Napi;

Value Echo(const CallbackInfo& info) {
    // You need to validate the arguments here.
    Function cb = info[1].As<Function>();
    std::string in = info[0].As<String>();
    EchoWorker* wk = new EchoWorker(cb, in);
    wk->Queue();
    return info.Env().Undefined();