HarmonyOS 鸿蒙Next 使用Node-API接口进行线程安全开发,使用文档中的代码片段执行结果是无法完成回调。大佬能给一个完整demo吗?

HarmonyOS 鸿蒙Next 使用Node-API接口进行线程安全开发,使用文档中的代码片段执行结果是无法完成回调。大佬能给一个完整demo吗?

.cpp文件代码

```cpp
#include "napi/native_api.h"
#include <future>

struct CallbackData {
    napi_threadsafe_function tsfn;
    napi_async_work work;
};

static napi_value ResolvedCallback(napi_env env, napi_callback_info info) {
    void *data = nullptr;
    size_t argc = 1;
    napi_value argv[1];
    if (napi_get_cb_info(env, info, &argc, argv, nullptr, &data) != napi_ok) {
        return nullptr;
    }
    size_t result = 0;
    char buf[32] = {0};
    napi_get_value_string_utf8(env, argv[0], buf, 32, &result);
    reinterpret_cast<std::promise<std::string>*>(data)->set_value(std::string(buf));
    return nullptr;
}

static napi_value RejectedCallback(napi_env env, napi_callback_info info) {
    void *data = nullptr;
    if (napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data) != napi_ok) {
        return nullptr;
    }
    reinterpret_cast<std::promise<std::string>*>(data)->set_exception(
        std::make_exception_ptr(std::runtime_error("Error in jsCallback")));
    return nullptr;
}

static void CallJs(napi_env env, napi_value jsCb, void *context, void *data) {
    if (env == nullptr) {
        return;
    }
    napi_value undefined = nullptr;
    napi_value promise = nullptr;
    napi_get_undefined(env, &undefined);
    napi_call_function(env, undefined, jsCb, 0, nullptr, &promise);
    napi_value thenFunc = nullptr;
    if (napi_get_named_property(env, promise, "then", &thenFunc) != napi_ok) {
        return;
    }
    napi_value resolvedCallback;
    napi_value rejectedCallback;
    napi_create_function(env, "resolvedCallback", NAPI_AUTO_LENGTH, ResolvedCallback, data, &resolvedCallback);
    napi_create_function(env, "rejectedCallback", NAPI_AUTO_LENGTH, RejectedCallback, data, &rejectedCallback);
    napi_value argv[2] = {resolvedCallback, rejectedCallback};
    napi_call_function(env, promise, thenFunc, 2, argv, nullptr);
}

static void WorkComplete(napi_env env, napi_status status, void *data) {
    CallbackData *callbackData = reinterpret_cast<CallbackData*>(data);
    napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
    napi_delete_async_work(env, callbackData->work);
    callbackData->tsfn = nullptr;
    callbackData->work = nullptr;
}

static void ExecuteWork(napi_env env, void *data) {
    CallbackData *callbackData = reinterpret_cast<CallbackData*>(data);
    std::promise<std::string> promise;
    auto future = promise.get_future();
    napi_call_threadsafe_function(callbackData->tsfn, &promise, napi_tsfn_nonblocking);
    try {
        auto result = future.get();
        // OH_LOG_INFO(LOG_APP, "XXX, Result from JS %{public}s", result.c_str());
    } catch (const std::exception &e) {
        // OH_LOG_INFO(LOG_APP, "XXX, Result from JS %{public}s", e.what());
    }
}

static napi_value StartThread(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value jsCb = nullptr;
    CallbackData *callbackData = nullptr;
    napi_get_cb_info(env, info, &argc, &jsCb, nullptr, reinterpret_cast<void**>(&callbackData));

    // 创建一个线程安全函数
    napi_value resourceName = nullptr;
    napi_create_string_utf8(env, "Thread-safe Function Demo", NAPI_AUTO_LENGTH, &resourceName);
    napi_create_threadsafe_function(env, jsCb, nullptr, resourceName, 0, 1, callbackData, nullptr,
                                    callbackData, CallJs, &callbackData->tsfn);

    // 创建一个异步任务
    napi_create_async_work(env, nullptr, resourceName, ExecuteWork, WorkComplete, callbackData,
                           &callbackData->work);

    // 将异步任务加入到异步队列中
    napi_queue_async_work(env, callbackData->work);
    return nullptr;
}

EXTERN_C_START
// 模块初始化
static napi_value Init(napi_env env, napi_value exports) {
    CallbackData *callbackData = new CallbackData(); // 可在线程退出时释放
    napi_property_descriptor desc[] = {
        {"startThread", nullptr, StartThread, nullptr, nullptr, nullptr, napi_default, callbackData},
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

// 模块基本信息
static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    // import时填写的.so名称--lib****.so
    .nm_modname = "entry",
    .nm_priv = nullptr,
    .reserved = {0},
};

// 加载so时,该函数会自动被调用,将上述demoModule模块注册到系统中。
extern "C" __attribute__((constructor))
void RegisterDemoModule() {
    napi_module_register(&demoModule);
}

更多关于HarmonyOS 鸿蒙Next 使用Node-API接口进行线程安全开发,使用文档中的代码片段执行结果是无法完成回调。大佬能给一个完整demo吗?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

建议通过在线提单进一步解决:https://developer.huawei.com/consumer/cn/support/feedback/#/

更多关于HarmonyOS 鸿蒙Next 使用Node-API接口进行线程安全开发,使用文档中的代码片段执行结果是无法完成回调。大佬能给一个完整demo吗?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中使用Node-API进行线程安全开发时,确保回调函数正确执行需要注意几个关键点。以下是一个简单的示例,展示如何使用Node-API创建线程并执行回调:

#include <napi.h>
#include <thread>
#include <iostream>

void AsyncWork(napi_env env, void* data) {
    // 模拟耗时操作
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Async work completed" << std::endl;
}

void Callback(napi_env env, napi_status status, void* data) {
    std::cout << "Callback executed" << std::endl;
}

Napi::Value StartAsyncWork(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    napi_async_work work;
    napi_create_async_work(env, nullptr, Napi::String::New(env, "AsyncWork"), AsyncWork, Callback, nullptr, &work);
    napi_queue_async_work(env, work);

    return Napi::Boolean::New(env, true);
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports.Set(Napi::String::New(env, "startAsyncWork"), Napi::Function::New(env, StartAsyncWork));
    return exports;
}

NODE_API_MODULE(addon, Init)

在这个示例中,StartAsyncWork函数创建了一个异步工作项napi_async_work,并将其加入队列。AsyncWork函数模拟了一个耗时操作,而Callback函数则在工作完成后被调用。

确保以下几点:

  1. napi_create_async_worknapi_queue_async_work正确使用。
  2. 回调函数Callback在异步工作完成后被调用。
  3. 环境变量env在所有函数中正确传递。

此代码片段展示了如何在鸿蒙Next中使用Node-API进行线程安全开发,并确保回调函数正确执行。

回到顶部