智能客服
你问我答,随时在线为你解决问题
napi_create_async_work是Node-API接口之一,用于创建一个异步工作对象。在需要执行耗时操作的场景中使用,避免阻塞env所在的ArkTS线程,确保应用程序的性能和响应速度。例如以下场景:
文件操作:读取大型文件或执行复杂的文件操作时,可以使用异步工作对象来避免阻塞env所在的ArkTS线程。
网络请求:当需要进行网络请求并等待响应时,使用异步工作对象确保主线程不被阻塞,提高应用程序的响应性能。
数据库操作:当需要执行复杂的数据库查询或写入操作时,使用异步工作对象确保主线程不被阻塞,提高应用程序的并发性能。
图像处理:当需要对大型图像进行处理或执行复杂的图像算法时,使用异步工作对象确保主线程不被阻塞,提高应用程序的实时性能。
napi_queue_async_work接口使用uv_queue_work能力,并管理回调中napi_value的生命周期。
异步调用支持callback和Promise两种方式,选择哪种方式由开发者决定。以下是两种方式的示例代码:


CMakeLists.txt配置
- # the minimum version of CMake.
- cmake_minimum_required(VERSION 3.5.0)
- project(NodeAPIAsynchronousTask)
-
- set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
-
- if(DEFINED PACKAGE_FIND_FILE)
- include(${PACKAGE_FIND_FILE})
- endif()
-
- include_directories(${NATIVERENDER_ROOT_PATH}
- ${NATIVERENDER_ROOT_PATH}/include)
-
- add_library(entry SHARED napi_init.cpp)
- target_link_libraries(entry PUBLIC libace_napi.z.so)
-
- add_library(entry1 SHARED callback.cpp)
- target_link_libraries(entry1 PUBLIC libace_napi.z.so)
使用napi_create_async_work创建异步任务,使用napi_queue_async_work将任务加入队列,等待执行。
- #include "napi/native_api.h"
- // 调用方提供的data context,该数据会传递给execute和complete函数
- struct CallbackData {
- napi_async_work asyncWork = nullptr;
- napi_deferred deferred = nullptr;
- napi_ref callback = nullptr;
- double args = 0;
- double result = 0;
- };
-
- // ...
-
- static napi_value AsyncWork(napi_env env, napi_callback_info info)
- {
- size_t argc = 1;
- napi_value args[1];
- napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
-
- napi_value promise = nullptr;
- napi_deferred deferred = nullptr;
- napi_create_promise(env, &deferred, &promise);
-
- auto callbackData = new CallbackData();
- callbackData->deferred = deferred;
- napi_get_value_double(env, args[0], &callbackData->args);
-
- napi_value resourceName = nullptr;
- napi_create_string_utf8(env, "AsyncCallback", NAPI_AUTO_LENGTH, &resourceName);
- // 创建异步任务
- napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB, callbackData, &callbackData->asyncWork);
- // 将异步任务加入队列
- napi_queue_async_work(env, callbackData->asyncWork);
-
- return promise;
- }
定义异步任务的第一个回调函数,该函数在工作线程中执行,处理具体的业务逻辑。
- static void ExecuteCB(napi_env env, void *data)
- {
- CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
- callbackData->result = callbackData->args;
- }
定义异步任务的第二个回调函数,该函数在主线程执行,将结果传递给ArkTS侧。
- static void CompleteCB(napi_env env, napi_status status, void *data)
- {
- CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
- napi_value result = nullptr;
- napi_create_double(env, callbackData->result, &result);
- if (callbackData->result > 0) {
- napi_resolve_deferred(env, callbackData->deferred, result);
- } else {
- napi_reject_deferred(env, callbackData->deferred, result);
- }
-
- napi_delete_async_work(env, callbackData->asyncWork);
- delete callbackData;
- callbackData = nullptr;
- }
模块注册及ArkTS侧调用接口。
- // 模块初始化
- static napi_value Init(napi_env env, napi_value exports)
- {
- napi_property_descriptor desc[] = {
- { "asyncWork", nullptr, AsyncWork, nullptr, nullptr, nullptr, napi_default, nullptr }
- };
- napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
- return exports;
- }
接口对应的.d.ts描述。
- // index.d.ts
- export const asyncWork: (data: number) => Promise<number>;
ArkTS侧调用接口。
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import testNapi from 'libentry.so';
- testNapi.asyncWork(1024).then((result: number) => {
- hilog.info(0x0000, 'XXX', 'result is %{public}d', result);
- });
- 运行结果:result is 1024

使用napi_create_async_work创建异步任务,并使用napi_queue_async_work将异步任务加入队列,等待执行。
- #include "napi/native_api.h"
-
- static constexpr int INT_ARGS_2 = 2; // 入参索引
-
- // 调用方提供的data context,该数据会传递给execute和complete函数
- struct CallbackData {
- napi_async_work asyncWork = nullptr;
- napi_ref callbackRef = nullptr;
- double args[2] = {0};
- double result = 0;
- };
-
- // ...
- napi_value AsyncWork(napi_env env, napi_callback_info info)
- {
- size_t argc = 3;
- napi_value args[3];
- napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
- auto asyncContext = new CallbackData();
- // 将接收到的参数保存到callbackData
- napi_get_value_double(env, args[0], &asyncContext->args[0]);
- napi_get_value_double(env, args[1], &asyncContext->args[1]);
- // 将传入的callback转换为napi_ref延长其生命周期,防止被GC掉
- napi_create_reference(env, args[INT_ARGS_2], 1, &asyncContext->callbackRef);
- napi_value resourceName = nullptr;
- napi_create_string_utf8(env, "asyncWorkCallback", NAPI_AUTO_LENGTH, &resourceName);
- // 创建异步任务
- napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB,
- asyncContext, &asyncContext->asyncWork);
- // 将异步任务加入队列
- napi_queue_async_work(env, asyncContext->asyncWork);
- return nullptr;
- }
定义异步任务的第一个回调函数,该函数在工作线程中执行,处理具体的业务逻辑。
- static void ExecuteCB(napi_env env, void *data)
- {
- CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
- callbackData->result = callbackData->args[0] + callbackData->args[1];
- }
定义异步任务的第二个回调函数,该函数在主线程执行,将结果传递给ArkTS侧。
- static void CompleteCB(napi_env env, napi_status status, void *data)
- {
- CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
- napi_value callbackArg[1] = {nullptr};
- napi_create_double(env, callbackData->result, &callbackArg[0]);
- napi_value callback = nullptr;
- napi_get_reference_value(env, callbackData->callbackRef, &callback);
- // 执行回调函数
- napi_value result;
- napi_value undefined;
- napi_get_undefined(env, &undefined);
- napi_call_function(env, undefined, callback, 1, callbackArg, &result);
- // 删除napi_ref对象以及异步任务
- napi_delete_reference(env, callbackData->callbackRef);
- napi_delete_async_work(env, callbackData->asyncWork);
- delete callbackData;
- callbackData = nullptr;
- }
模块注册以及ArkTS侧调用接口。
导出方法名与上面一致,可直接复用模块注册的代码。
- // 模块初始化
- static napi_value Init(napi_env env, napi_value exports)
- {
- napi_property_descriptor desc[] = {
- { "asyncWork", nullptr, AsyncWork, nullptr, nullptr, nullptr, napi_default, nullptr }
- };
- napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
- return exports;
- }
接口对应的.d.ts描述。
- export const asyncWork: (arg1: number, arg2: number, callback: (result: number) => void) => void;
ArkTS侧调用接口。
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import nativeModule from 'libentry1.so';
-
- let num1: number = 123;
- let num2: number = 456;
- nativeModule.asyncWork(num1, num2, (result: number) => {
- hilog.info(0x0000, 'XXX', 'result is %{public}d', result);
- });
- 运行结果:result is 579
Worker配置。
- "buildOption": {
- "sourceOption": {
- "workers": [
- "./src/main/ets/workers/Worker.ets"
- ]
- },
- }
Worker线程示例代码。
- // entry/src/main/ets/workers/Worker.ets
-
- import nativeModule from 'libentry1.so';
- import { worker, MessageEvents } from '@kit.ArkTS';
-
- const port = worker.workerPort;
-
- port.onmessage = (e : MessageEvents) => {
- console.info('Worker thread received data:', e.data.num1 + '、' + e.data.num2);
- nativeModule.asyncWork(e.data.num1, e.data.num2, (result: number) => {
- port.postMessage(result);
- });
- }
ArkTS线程代码。
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import { worker } from '@kit.ArkTS';
- let num1: number = 123;
- let num2: number = 456;
- const wk = new worker.ThreadWorker('entry/ets/workers/Worker.ets');
- wk.postMessage({num1, num2});
- wk.onmessage = (msg) => {
- console.info('result is:', msg.data);
- wk.terminate();
- }
- 运行结果:
- Worker thread received data: 123、456
- result is 579
ArkTS线程代码。
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import { taskpool } from '@kit.ArkTS';
- import nativeModule from 'libentry1.so';
- let num1: number = 123;
- let num2: number = 456;
-
- @Concurrent
- function nativeCall(num1 : number, num2 : number): void {
- console.info('Taskpool thread received data:', + num1 + '、' + num2);
- nativeModule.asyncWork(num1, num2, (result: number) => {
- hilog.info(0x0000, 'XXX', 'result is: %{public}d', result);
- });
- }
-
- async function testTaskpool() : Promise<void> {
- try {
- const task = new taskpool.Task(nativeCall, num1, num2);
- await taskpool.execute(task);
- } catch (e) {
- console.error(`Taskpool execute error: ${e}`);
- }
- }
- testTaskpool();
- 运行结果:
- Taskpool thread received data: 123、456
- result is 579