1# Customizing Asynchronous Operations Using Node-API 2 3## Introduction 4 5Node-API provides APIs for customizing asynchronous (async for short) operations to handle time-consuming tasks that may block event loops while maintaining quick response and high performance of ArkTS applications. 6 7## Basic Concepts 8 9Async operations are used to complete I/O-intensive or compute-intensive tasks, which usually need to be executed without blocking the main thread. Before you get started, understand the following concepts: 10 11- Async model: Node-API provides APIs that implement async operations using a promise or a callback. Promise is a programming model based on future values. It allows results of async operations to be encapsulated in objects and called in a chain. Callback is a traditional async programming mode. It uses callback functions to process async operation results. 12- Temporary result: When a native method (Node-API) is called, it immediately returns a temporary result to the ArkTS caller. The temporary result is usually a flag indicating an async operation being performed or a handle for subsequent processing of an async operation result. 13- Callback/Promise: When an async operation is complete, the result is returned to the ArkTS caller through a callback function or a promise object. This allows the processing of the subsequent logic after the async operation is complete. 14 15## Available APIs 16 17The following table lists the APIs provided by the Node-API module for customizing async operations. You can use these APIs to implement ArkTS callbacks and manage the resource lifecycle in C/C++. These APIs help implement complex async operations and effective interaction with ArkTS. 18| API| Description| 19| -------- | -------- | 20| napi_async_init, napi_async_destroy| Creates/Destroys an async context. <br/>You can use these APIs to handle time-consuming tasks, such as file I/O operations and network requests, without blocking the main thread. You can use **napi_async_init** to create an async context for executing the task, and use **napi_async_destroy** after the task is complete to destroy and release related resources.| 21| napi_make_callback | Executes an ArkTS callback function in an async context and returns the operation result to ArkTS.| 22| napi_open_callback_scope, napi_close_callback_scope| Opens/Closes a callback scope. You can use these APIs to execute ArkTS code and manage its context during the async operation.| 23 24## Example 25 26If you are just starting out with Node-API, see [Node-API Development Process](use-napi-process.md). The following demonstrates only the C++ and ArkTS code involved in the APIs for customizing async operations. 27 28### napi_async_init and napi_async_destroy 29 30Use **napi_async_init** to create an async context, and use **napi_async_destroy** to destroy an async context. Note that these APIs do not support capabilities related to **async_hook**. 31 32### napi_make_callback 33 34To call and execute an ArkTS callback after an async operation is complete, use **napi_make_callback**. 35 36### napi_open_callback_scope and napi_close_callback_scope 37 38To make the ArkTS context still available during an async operation, use **napi_open_callback_scope** to create a scope for the callback. You can use **napi_close_callback_scope** to close the scope after the async operation is complete. 39 40CPP code: 41 42```cpp 43#include "napi/native_api.h" 44 45static napi_value AsynchronousWork(napi_env env, napi_callback_info info) 46{ 47 // Initialize an array to hold four parameters. 48 size_t argc = 4; 49 napi_value args[4] = {nullptr}; 50 // Obtain parameters from the callback information. 51 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 52 // Extract resources, receiver objects, and functions from the parameters. 53 napi_value resource = args[0]; 54 napi_value recv = args[1]; 55 napi_value func = args[2]; 56 napi_value argv[1] = {nullptr}; 57 argv[0] = args[3]; 58 // Obtain the function type. 59 napi_valuetype funcType; 60 napi_typeof(env, func, &funcType); 61 // Create a string named "test". 62 napi_value resourceName = nullptr; 63 napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &resourceName); 64 // Initialize the async context. 65 napi_async_context context; 66 napi_status status = napi_async_init(env, resource, resourceName, &context); 67 if (status != napi_ok) { 68 napi_throw_error(env, nullptr, "napi_async_init fail"); 69 return nullptr; 70 } 71 // Open a callback scope. 72 napi_callback_scope scope = nullptr; 73 napi_open_callback_scope(env, resource, context, &scope); 74 if (status != napi_ok) { 75 napi_throw_error(env, nullptr, "napi_open_callback_scope fail"); 76 return nullptr; 77 } 78 // Invoke the callback function defined. 79 napi_value result = nullptr; 80 if (funcType == napi_function) { 81 napi_make_callback(env, context, recv, func, 1, argv, &result); 82 } else { 83 napi_throw_error(env, nullptr, "Unexpected argument type"); 84 return nullptr; 85 } 86 // Close the callback scope. 87 napi_close_callback_scope(env, scope); 88 if (status != napi_ok) { 89 napi_throw_error(env, nullptr, "napi_close_callback_scope fail"); 90 return nullptr; 91 } 92 // Destroy the async context. 93 napi_async_destroy(env, context); 94 return result; 95} 96``` 97 98API declaration: 99 100```ts 101// index.d.ts 102export const asynchronousWork: (object: Object, obj: Object, fun: Function, num: number) => number | void; 103``` 104 105ArkTS code: 106 107```ts 108import hilog from '@ohos.hilog' 109import testNapi from 'libentry.so' 110import process from '@ohos.process' 111try { 112 hilog.info(0x0000, 'testTag', 'Test Node-API asynchronousWork: %{public}d', testNapi.asynchronousWork({}, process.ProcessManager, (num: number)=>{return num;}, 123)); 113} catch (error) { 114 hilog.error(0x0000, 'testTag', 'Test Node-API asynchronousWork error: %{public}s', error.message); 115} 116``` 117 118To print logs in the native CPP, add the following information to the **CMakeLists.txt** file and add the header file by using **#include "hilog/log.h"**. 119 120```text 121// CMakeLists.txt 122add_definitions( "-DLOG_DOMAIN=0xd0d0" ) 123add_definitions( "-DLOG_TAG=\"testTag\"" ) 124target_link_libraries(entry PUBLIC libhilog_ndk.z.so ) 125``` 126