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