1# 使用Node-API进行自定义异步操作相关开发 2<!--Kit: NDK--> 3<!--Subsystem: arkcompiler--> 4<!--Owner: @xliu-huanwei; @shilei123; @huanghello--> 5<!--Designer: @shilei123--> 6<!--Tester: @kirl75; @zsw_zhushiwei--> 7<!--Adviser: @fang-jinxu--> 8 9## 简介 10 11使用Node-API的自定义异步操作功能,可以使ArkTS更灵活高效地处理那些可能阻塞事件循环的长时间运行任务,同时保持应用的响应性和性能。 12 13## 基本概念 14 15Node-API支持异步操作,这有助于处理IO密集型或计算密集型任务。这些任务通常需要非阻塞的执行方式,以避免阻塞主线程。以下是一些关于自定义异步操作的基本概念: 16 17- **异步模型:** Node-API支持异步模型,提供了Promise和Callback两种方式来实现异步操作。Promise是一种基于未来值的编程模型,它允许开发者将异步操作的结果封装在一个对象中,并通过链式调用的方式处理异步操作的结果。Callback则是一种传统的异步编程方式,通过回调函数来处理异步操作的结果。 18- **临时结果:** 当原生方法(即Node-API代码)被调用时,它会立即返回一个临时结果给ArkTS调用者。这个临时结果通常是一个表示异步操作正在进行中的标志,或者是用于后续处理异步操作结果的句柄。 19- **回调或Promise:** 当异步操作完成后,结果会通过回调函数或Promise对象返回给ArkTS调用者。这样,ArkTS代码就可以在异步操作完成后继续执行后续的逻辑。 20 21## 场景和功能介绍 22 23这些Node-API接口可以在Node-API模块中执行异步操作、进行ArkTS回调以及管理相关资源的生命周期。通过使用这些函数,可以有效地与ArkTS环境进行交互,并实现复杂的异步操作。它们的使用场景如下: 24| 接口 | 描述 | 25| -------- | -------- | 26| napi_async_init、napi_async_destroy | 用于创建和销毁异步资源上下文环境。这些函数可以用于处理长时间运行的异步操作,例如文件I/O操作、网络请求等。在这些情况下,创建异步资源上下文环境,执行必要的异步任务,然后销毁资源以释放相关的资源和内容。 | 27| napi_make_callback | 用于在异步资源上下文环境中执行ArkTS回调函数。在处理异步操作的结果后,将结果传递回ArkTS代码。 | 28| napi_open_callback_scope、napi_close_callback_scope | 用于创建和关闭回调作用域。在异步操作期间执行ArkTS代码并管理其上下文。 | 29 30## 使用示例 31 32Node-API接口开发流程参考[使用Node-API实现跨语言交互开发流程](use-napi-process.md),本文仅对接口对应C++及ArkTS相关代码进行展示。 33 34### napi_async_init、napi_async_destroy 35 36在需要管理异步资源上下文环境的创建和销毁时,可以使用napi_async_init和napi_async_destroy来管理这些环境。需要注意的是,这些函数不支持与async_hook相关的能力,所以在使用时需要注意可能存在的一些限制。 37 38### napi_make_callback 39 40在编写Node-API模块时,异步操作完成后需调用ArkTS回调函数。可使用napi_async_init创建异步资源上下文,再使用napi_make_callback执行ArkTS回调函数。 41 42### napi_open_callback_scope、napi_close_callback_scope 43 44在需要创建一个回调作用域来确保异步操作期间ArkTS环境仍然可用时,可以使用napi_open_callback_scope创建回调作用域,然后在异步操作完成后使用napi_close_callback_scope关闭该作用域。 45 46cpp部分代码 47 48```cpp 49#include "napi/native_api.h" 50 51static constexpr int INT_ARG_2 = 2; // 入参索引 52static constexpr int INT_ARG_3 = 3; // 入参索引 53 54static napi_value AsynchronousWork(napi_env env, napi_callback_info info) 55{ 56 // 接受四个参数 57 size_t argc = 4; 58 napi_value args[4] = {nullptr}; 59 // 从回调信息中获取参数 60 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 61 // 提取参数中的资源、接收器对象和函数 62 napi_value resource = args[0]; 63 napi_value recv = args[1]; 64 napi_value func = args[INT_ARG_2]; 65 napi_value argv[1] = {nullptr}; 66 argv[0] = args[INT_ARG_3]; 67 // 获取函数的类型 68 napi_valuetype funcType; 69 napi_typeof(env, func, &funcType); 70 // 创建一个资源名称为"test"的字符串 71 napi_value resourceName = nullptr; 72 napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &resourceName); 73 // 初始化异步上下文 74 napi_async_context context; 75 napi_status status = napi_async_init(env, resource, resourceName, &context); 76 if (status != napi_ok) { 77 napi_throw_error(env, nullptr, "napi_async_init fail"); 78 return nullptr; 79 } 80 // 打开回调作用域 81 napi_callback_scope scope = nullptr; 82 status = napi_open_callback_scope(env, resource, context, &scope); 83 if (status != napi_ok) { 84 napi_throw_error(env, nullptr, "napi_open_callback_scope fail"); 85 return nullptr; 86 } 87 // 调用回调函数 88 napi_value result = nullptr; 89 if (funcType == napi_function) { 90 napi_make_callback(env, context, recv, func, 1, argv, &result); 91 } else { 92 napi_throw_error(env, nullptr, "Unexpected argument type"); 93 return nullptr; 94 } 95 // 关闭回调作用域 96 status = napi_close_callback_scope(env, scope); 97 if (status != napi_ok) { 98 napi_throw_error(env, nullptr, "napi_close_callback_scope fail"); 99 return nullptr; 100 } 101 // 销毁异步上下文 102 napi_async_destroy(env, context); 103 return result; 104} 105``` 106<!-- @[napi_async_open_close_callback_scope](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPICustomAsynchronousOperations/entry/src/main/cpp/napi_init.cpp) --> 107 108接口声明 109 110```ts 111// index.d.ts 112export const asynchronousWork: (object: Object, obj: Object, fun: Function, num: number) => number | undefined; 113``` 114<!-- @[napi_async_open_close_callback_scope_api](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPICustomAsynchronousOperations/entry/src/main/cpp/types/libentry/Index.d.ts) --> 115 116ArkTS侧示例代码 117 118```ts 119import { hilog } from '@kit.PerformanceAnalysisKit'; 120import testNapi from 'libentry.so'; 121import process from '@ohos.process'; 122try { 123 hilog.info(0x0000, 'testTag', 'Test Node-API asynchronousWork: %{public}d', testNapi.asynchronousWork({}, process.ProcessManager, (num: number)=>{return num;}, 123)); 124} catch (error) { 125 hilog.error(0x0000, 'testTag', 'Test Node-API asynchronousWork error: %{public}s', error.message); 126} 127``` 128<!-- @[ark_napi_async_open_close_callback_scope](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIUse/NodeAPICustomAsynchronousOperations/entry/src/main/ets/pages/Index.ets) --> 129 130以上代码如果要在native cpp中打印日志,需在CMakeLists.txt文件中添加以下配置信息(并添加头文件:#include "hilog/log.h"): 131 132```text 133// CMakeLists.txt 134add_definitions( "-DLOG_DOMAIN=0xd0d0" ) 135add_definitions( "-DLOG_TAG=\"testTag\"" ) 136target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so) 137``` 138