1e41f4b71Sopenharmony_ci# Implementing Asynchronous Operations Using Node-API 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Introduction 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciNode-API provides APIs for implementing asynchronous operations for time-consuming tasks, such as downloading data from network or reading a large file. Different from synchronous operations, asynchronous operations are executed in the background without blocking the main thread. When an asynchronous operation is complete, it will be added to the task queue and executed when the main thread is idle. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci## Basic Concepts 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci**Promise** is an object used to handle asynchronous operations in ArkTS. It has three states: **pending**, **fulfilled**, and **rejected**. The initial state is **pending**, which can be changed to **fulfilled** by **resolve()** and to **rejected** by **reject()**. Once the state is **fulfilled** or **rejected**, the promise state cannot be changed. Read on the following to learn basic concepts related to **Promise**: 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci- Synchronous: Code is executed line by line in sequence. Each line of code is executed after the previous line of code is executed. During synchronous execution, if an operation takes a long time, the execution of the entire application will be blocked until the operation is complete. 12e41f4b71Sopenharmony_ci- Asynchronous: Tasks can be executed concurrently without waiting for the end of the previous task. In ArkTS, common asynchronous operations apply for timers, event listening, and network requests. Instead of blocking subsequent tasks, the asynchronous task uses a callback or promise to process its result. 13e41f4b71Sopenharmony_ci- **Promise**: an ArkTS object used to handle asynchronous operations. Generally, it is exposed externally by using **then()**, **catch()**, or **finally()** to custom logic. 14e41f4b71Sopenharmony_ci- **deferred**: a utility object associated with the **Promise** object to set **resolve()** and **reject()** of **Promise**. It is used internally to maintain the state of the asynchronous model and set the **resolve()** and **reject()** callbacks. 15e41f4b71Sopenharmony_ci- **resolve**: a function used to change the promise state from **pending** to **fulfilled**. The parameters passed to **resolve()** can be obtained from **then()** of the **Promise** object. 16e41f4b71Sopenharmony_ci- **reject**: a function used to change the promise state from **pending** to **rejected**. The parameters passed to **reject()** can be obtained from **catch()** of the **Promise** object. 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci**Promise** allows multiple callbacks to be called in a chain, providing better code readability and a better way to deal with asynchronous operations. The APIs provided by the Node-API module help you flexibly process ArkTS asynchronous operations in C/C++. 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci## Available APIs 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ciThe following table lists the APIs for implementing asynchronous operations using ArkTS promises. 23e41f4b71Sopenharmony_ci| API| Description| 24e41f4b71Sopenharmony_ci| -------- | -------- | 25e41f4b71Sopenharmony_ci| napi_is_promise | Checks whether a **napi_value** is a **Promise** object.| 26e41f4b71Sopenharmony_ci| napi_create_promise | Creates a **Promise** object.| 27e41f4b71Sopenharmony_ci| napi_resolve_deferred | Resolves a promise by using the **deferred** object associated with it.| 28e41f4b71Sopenharmony_ci| napi_reject_deferred | Rejects a promise by using the **deferred** object associated with it| 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci## Example 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ciIf 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 related to promises. 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci### napi_is_promise 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ciUse **napi_is_promise** to check whether the given **napi_value** is a **Promise** object. 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ciCPP code: 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci```cpp 41e41f4b71Sopenharmony_ci#include "napi/native_api.h" 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_cistatic napi_value IsPromise(napi_env env, napi_callback_info info) 44e41f4b71Sopenharmony_ci{ 45e41f4b71Sopenharmony_ci napi_value argv[1] = {nullptr}; 46e41f4b71Sopenharmony_ci size_t argc = 1; 47e41f4b71Sopenharmony_ci napi_status status; 48e41f4b71Sopenharmony_ci // Obtain the parameters passed in. 49e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 50e41f4b71Sopenharmony_ci bool isPromise = false; 51e41f4b71Sopenharmony_ci // Check whether the given parameter is a Promise object and save the result in the isPromise variable. 52e41f4b71Sopenharmony_ci status = napi_is_promise(env, argv[0], &isPromise); 53e41f4b71Sopenharmony_ci if (status != napi_ok) { 54e41f4b71Sopenharmony_ci napi_throw_error(env, nullptr, "Node-API napi_is_promise failed"); 55e41f4b71Sopenharmony_ci return nullptr; 56e41f4b71Sopenharmony_ci } 57e41f4b71Sopenharmony_ci napi_value result = nullptr; 58e41f4b71Sopenharmony_ci // Convert the value of isPromise to the type specified by napi_value, and return it. 59e41f4b71Sopenharmony_ci napi_get_boolean(env, isPromise, &result); 60e41f4b71Sopenharmony_ci return result; 61e41f4b71Sopenharmony_ci} 62e41f4b71Sopenharmony_ci``` 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ciAPI declaration: 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci```ts 67e41f4b71Sopenharmony_ci// index.d.ts 68e41f4b71Sopenharmony_ciexport const isPromise: <T>(value: T) => boolean; 69e41f4b71Sopenharmony_ci``` 70e41f4b71Sopenharmony_ci 71e41f4b71Sopenharmony_ciArkTS code: 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci```ts 74e41f4b71Sopenharmony_ciimport hilog from '@ohos.hilog' 75e41f4b71Sopenharmony_ciimport testNapi from 'libentry.so' 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_cilet value = Promise.resolve(); 78e41f4b71Sopenharmony_ci// Return true if the object passed in is a promise; return false otherwise. 79e41f4b71Sopenharmony_cihilog.info(0x0000, 'Node-API', 'napi_is_promise %{public}s', testNapi.isPromise(value)); 80e41f4b71Sopenharmony_cihilog.info(0x0000, 'Node-API', 'napi_is_promise string %{public}s', testNapi.isPromise('')); 81e41f4b71Sopenharmony_ci``` 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci### napi_create_promise 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ciUse **napi_create_promise** to create a **Promise** object. 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci### napi_resolve_deferred & napi_reject_deferred 88e41f4b71Sopenharmony_ci 89e41f4b71Sopenharmony_ciUse **napi_resolve_deferred** to change the promise state from **pending** to **fulfilled**, and use **napi_reject_deferred** to change the promise state from **pending** to **rejected**. 90e41f4b71Sopenharmony_ci 91e41f4b71Sopenharmony_ciCPP code: 92e41f4b71Sopenharmony_ci 93e41f4b71Sopenharmony_ci```cpp 94e41f4b71Sopenharmony_ci#include "napi/native_api.h" 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_cistatic napi_value CreatePromise(napi_env env, napi_callback_info info) 97e41f4b71Sopenharmony_ci{ 98e41f4b71Sopenharmony_ci // The deferred object is used to delay the execution of a function for a certain period of time. 99e41f4b71Sopenharmony_ci napi_deferred deferred = nullptr; 100e41f4b71Sopenharmony_ci napi_value promise = nullptr; 101e41f4b71Sopenharmony_ci // Create a Promise object. 102e41f4b71Sopenharmony_ci napi_status status = napi_create_promise(env, &deferred, &promise); 103e41f4b71Sopenharmony_ci if (status != napi_ok) { 104e41f4b71Sopenharmony_ci napi_throw_error(env, nullptr, "Create promise failed"); 105e41f4b71Sopenharmony_ci return nullptr; 106e41f4b71Sopenharmony_ci } 107e41f4b71Sopenharmony_ci //Call napi_is_promise to check whether the object created by napi_create_promise is a Promise object. 108e41f4b71Sopenharmony_ci bool isPromise = false; 109e41f4b71Sopenharmony_ci napi_value returnIsPromise = nullptr; 110e41f4b71Sopenharmony_ci napi_is_promise(env, promise, &isPromise); 111e41f4b71Sopenharmony_ci // Convert the Boolean value to napi_value and return it. 112e41f4b71Sopenharmony_ci napi_get_boolean(env, isPromise, &returnIsPromise); 113e41f4b71Sopenharmony_ci return returnIsPromise; 114e41f4b71Sopenharmony_ci} 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_cistatic napi_value ResolveRejectDeferred(napi_env env, napi_callback_info info) 117e41f4b71Sopenharmony_ci{ 118e41f4b71Sopenharmony_ci // Obtain and parse parameters. 119e41f4b71Sopenharmony_ci size_t argc = 3; 120e41f4b71Sopenharmony_ci napi_value args[3] = {nullptr}; 121e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 122e41f4b71Sopenharmony_ci // The first parameter is the data to be passed to Resolve(), the second parameter is the data to be passed to reject(), and the third parameter is the Promise state. 123e41f4b71Sopenharmony_ci bool status; 124e41f4b71Sopenharmony_ci napi_get_value_bool(env, args[2], &status); 125e41f4b71Sopenharmony_ci // Create a Promise object. 126e41f4b71Sopenharmony_ci napi_deferred deferred = nullptr; 127e41f4b71Sopenharmony_ci napi_value promise = nullptr; 128e41f4b71Sopenharmony_ci napi_status createStatus = napi_create_promise(env, &deferred, &promise); 129e41f4b71Sopenharmony_ci if (createStatus != napi_ok) { 130e41f4b71Sopenharmony_ci napi_throw_error(env, nullptr, "Create promise failed"); 131e41f4b71Sopenharmony_ci return nullptr; 132e41f4b71Sopenharmony_ci } 133e41f4b71Sopenharmony_ci // Set the promise state based on the third parameter. 134e41f4b71Sopenharmony_ci if (status) { 135e41f4b71Sopenharmony_ci napi_resolve_deferred(env, deferred, args[0]); 136e41f4b71Sopenharmony_ci } else { 137e41f4b71Sopenharmony_ci napi_reject_deferred(env, deferred, args[1]); 138e41f4b71Sopenharmony_ci } 139e41f4b71Sopenharmony_ci // Return the Promise object with the state set. 140e41f4b71Sopenharmony_ci return promise; 141e41f4b71Sopenharmony_ci} 142e41f4b71Sopenharmony_ci``` 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ciAPI declaration: 145e41f4b71Sopenharmony_ci 146e41f4b71Sopenharmony_ci```ts 147e41f4b71Sopenharmony_ci// index.d.ts 148e41f4b71Sopenharmony_ciexport const createPromise: () => boolean | void; 149e41f4b71Sopenharmony_ciexport const resolveRejectDeferred: (resolve: string, reject: string, status: boolean) => Promise<string> | void; 150e41f4b71Sopenharmony_ci``` 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ciArkTS code: 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ci```ts 155e41f4b71Sopenharmony_ciimport hilog from '@ohos.hilog' 156e41f4b71Sopenharmony_ciimport testNapi from 'libentry.so' 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci// Create a promise. Return true if the operation is successful, and return false otherwise. 159e41f4b71Sopenharmony_cihilog.info(0x0000, 'Node-API', 'napi_create_promise %{public}s', testNapi.createPromise()); 160e41f4b71Sopenharmony_ci// Call resolveRejectDeferred to resolve or reject the promise and set the promise state. 161e41f4b71Sopenharmony_ci// Resolve the promise. The return value is passed to the then function. 162e41f4b71Sopenharmony_cilet promiseSuccess: Promise<string> = testNapi.resolveRejectDeferred('success', 'fail', true) as Promise<string>; 163e41f4b71Sopenharmony_cipromiseSuccess.then((res) => { 164e41f4b71Sopenharmony_ci hilog.info(0x0000, 'Node-API', 'get_resolve_deferred resolve %{public}s', res) 165e41f4b71Sopenharmony_ci}).catch((err: Error) => { 166e41f4b71Sopenharmony_ci hilog.info(0x0000, 'Node-API', 'get_resolve_deferred reject %{public}s', err) 167e41f4b71Sopenharmony_ci}) 168e41f4b71Sopenharmony_ci// Reject the promise. The return value is passed to the catch function. 169e41f4b71Sopenharmony_cilet promiseFail: Promise<string> = testNapi.resolveRejectDeferred('success', 'fail', false) as Promise<string>; 170e41f4b71Sopenharmony_cipromiseFail.then((res) => { 171e41f4b71Sopenharmony_ci hilog.info(0x0000, 'Node-API', 'get_resolve_deferred resolve %{public}s', res) 172e41f4b71Sopenharmony_ci}).catch((err: Error) => { 173e41f4b71Sopenharmony_ci hilog.info(0x0000, 'Node-API', 'get_resolve_deferred reject %{public}s', err) 174e41f4b71Sopenharmony_ci}) 175e41f4b71Sopenharmony_ci``` 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ciTo 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"**. 178e41f4b71Sopenharmony_ci 179e41f4b71Sopenharmony_ci```text 180e41f4b71Sopenharmony_ci// CMakeLists.txt 181e41f4b71Sopenharmony_ciadd_definitions( "-DLOG_DOMAIN=0xd0d0" ) 182e41f4b71Sopenharmony_ciadd_definitions( "-DLOG_TAG=\"testTag\"" ) 183e41f4b71Sopenharmony_citarget_link_libraries(entry PUBLIC libhilog_ndk.z.so) 184e41f4b71Sopenharmony_ci``` 185