1# 使用Node-API接口进行异步任务开发 2 3## 场景介绍 4 5napi_create_async_work是Node-API接口之一,用于创建一个异步工作对象。可以在需要执行耗时操作的场景中使用,以避免阻塞主线程,确保应用程序的性能和响应性能。例如以下场景: 6 7- 文件操作:读取大型文件或执行复杂的文件操作时,可以使用异步工作对象来避免阻塞主线程。 8 9- 网络请求:当需要进行网络请求并等待响应时,使用异步工作对象可以确保主线程不被阻塞,从而提高应用程序的响应性能。 10 11- 数据库操作:当需要执行复杂的数据库查询或写入操作时,使用异步工作对象可以确保主线程不被阻塞,从而提高应用程序的并发性能。 12 13- 图像处理:当需要对大型图像进行处理或执行复杂的图像算法时,使用异步工作对象可以确保主线程不被阻塞,从而提高应用程序的实时性能。 14 15异步调用支持callback方式和Promise方式,使用哪种方式由应用开发者决定,通过是否传递callback函数进行区分。 16 17 18 19## 使用Promise方式示例 20 21 22 231. 使用napi_create_async_work创建异步任务,并使用napi_queue_async_work将异步任务加入队列,等待执行。 24 25 ```cpp 26 struct CallbackData { 27 napi_async_work asyncWork = nullptr; 28 napi_deferred deferred = nullptr; 29 napi_ref callback = nullptr; 30 double args = 0; 31 double result = 0; 32 }; 33 34 static napi_value AsyncWork(napi_env env, napi_callback_info info) 35 { 36 size_t argc = 1; 37 napi_value args[1]; 38 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 39 40 napi_value promise = nullptr; 41 napi_deferred deferred = nullptr; 42 napi_create_promise(env, &deferred, &promise); 43 44 auto callbackData = new CallbackData(); 45 callbackData->deferred = deferred; 46 napi_get_value_double(env, args[0], &callbackData->args); 47 48 napi_value resourceName = nullptr; 49 napi_create_string_utf8(env, "AsyncCallback", NAPI_AUTO_LENGTH, &resourceName); 50 // 创建异步任务 51 napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB, callbackData, &callbackData->asyncWork); 52 // 将异步任务加入队列 53 napi_queue_async_work(env, callbackData->asyncWork); 54 55 return promise; 56 } 57 ``` 58 592. 定义异步任务的第一个回调函数,该函数在工作线程中执行,处理具体的业务逻辑。 60 61 ```cpp 62 static void ExecuteCB(napi_env env, void *data) 63 { 64 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 65 callbackData->result = callbackData->args; 66 } 67 ``` 68 693. 定义异步任务的第二个回调函数,该函数在主线程执行,将结果传递给ArkTS侧。 70 71 ```cpp 72 static void CompleteCB(napi_env env, napi_status status, void *data) 73 { 74 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 75 napi_value result = nullptr; 76 napi_create_double(env, callbackData->result, &result); 77 if (callbackData->result > 0) { 78 napi_resolve_deferred(env, callbackData->deferred, result); 79 } else { 80 napi_reject_deferred(env, callbackData->deferred, result); 81 } 82 83 napi_delete_async_work(env, callbackData->asyncWork); 84 delete callbackData; 85 } 86 ``` 87 884. 模块初始化以及ArkTS侧调用接口。 89 90 ```cpp 91 // 模块初始化 92 static napi_value Init(napi_env env, napi_value exports) 93 { 94 napi_property_descriptor desc[] = { 95 { "asyncWork", nullptr, AsyncWork, nullptr, nullptr, nullptr, napi_default, nullptr } 96 }; 97 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 98 return exports; 99 } 100 ``` 101 102 ```ts 103 // 接口对应的.d.ts描述 104 export const asyncWork: (data: number) => Promise<number>; 105 106 // ArkTS侧调用接口 107 nativeModule.asyncWork(1024).then((result) => { 108 hilog.info(0x0000, 'XXX', 'result is %{public}d', result); 109 }); 110 ``` 111 112## 使用callback方式示例 113 114 115 1161. 使用napi_create_async_work创建异步任务,并使用napi_queue_async_work将异步任务加入队列,等待执行。 117 118 ```cpp 119 struct CallbackData { 120 napi_async_work asyncWork = nullptr; 121 napi_ref callbackRef = nullptr; 122 double args[2] = {0}; 123 double result = 0; 124 }; 125 126 napi_value AsyncWork(napi_env env, napi_callback_info info) 127 { 128 size_t argc = 3; 129 napi_value args[3]; 130 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 131 auto asyncContext = new CallbackData(); 132 // 将接收到的参数保存到callbackData 133 napi_get_value_double(env, args[0], &asyncContext->args[0]); 134 napi_get_value_double(env, args[1], &asyncContext->args[1]); 135 // 将传入的callback转换为napi_ref延长其生命周期,防止被GC掉 136 napi_create_reference(env, args[2], 1, &asyncContext->callbackRef); 137 napi_value resourceName = nullptr; 138 napi_create_string_utf8(env, "asyncWorkCallback", NAPI_AUTO_LENGTH, &resourceName); 139 // 创建异步任务 140 napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB, 141 asyncContext, &asyncContext->asyncWork); 142 // 将异步任务加入队列 143 napi_queue_async_work(env, asyncContext->asyncWork); 144 return nullptr; 145 } 146 ``` 147 1482. 定义异步任务的第一个回调函数,该函数在工作线程中执行,处理具体的业务逻辑。 149 150 ```cpp 151 static void ExecuteCB(napi_env env, void *data) 152 { 153 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 154 callbackData->result = callbackData->args[0] + callbackData->args[1]; 155 } 156 ``` 157 1583. 定义异步任务的第二个回调函数,该函数在主线程执行,将结果传递给ArkTS侧。 159 160 ```cpp 161 static void CompleteCB(napi_env env, napi_status status, void *data) 162 { 163 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 164 napi_value callbackArg[1] = {nullptr}; 165 napi_create_double(env, callbackData->result, &callbackArg[0]); 166 napi_value callback = nullptr; 167 napi_get_reference_value(env, callbackData->callbackRef, &callback); 168 // 执行回调函数 169 napi_value result; 170 napi_value undefined; 171 napi_get_undefined(env, &undefined); 172 napi_call_function(env, undefined, callback, 1, callbackArg, &result); 173 // 删除napi_ref对象以及异步任务 174 napi_delete_reference(env, callbackData->callbackRef); 175 napi_delete_async_work(env, callbackData->asyncWork); 176 delete callbackData; 177 } 178 ``` 179 1804. 模块初始化以及ArkTS侧调用接口。 181 182 ```cpp 183 // 模块初始化 184 static napi_value Init(napi_env env, napi_value exports) 185 { 186 napi_property_descriptor desc[] = { 187 { "asyncWork", nullptr, AsyncWork, nullptr, nullptr, nullptr, napi_default, nullptr } 188 }; 189 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 190 return exports; 191 } 192 ``` 193 194 ```ts 195 // 接口对应的.d.ts描述 196 export const asyncWork: (arg1: number, arg2: number, callback: (result: number) => void) => void; 197 198 // ArkTS侧调用接口 199 let num1: number = 123; 200 let num2: number = 456; 201 nativeModule.asyncWork(num1, num2, (result) => { 202 hilog.info(0x0000, 'XXX', 'result is %{public}d', result); 203 }); 204 ``` 205