1# Asynchronous Task Development Using Node-API 2 3## When to Use 4 5For a time-consuming operation, you can use **napi_create_async_work** to create an asynchronous work object to prevent the main thread from being blocked while ensuring the performance and response of your application. You can use asynchronous work objects in the following scenarios: 6 7- File operations: You can use asynchronous work objects in complex file operations or when a large file needs to be read to prevent the main thread from being blocked. 8 9- Network request: When your application needs to wait for a response to a network request, using an asynchronous worker object can improve its response performance without affecting the main thread. 10 11- Database operation: Using asynchronous work objects in complex database query or write operations can improve the concurrency performance of your application without compromising the running of the main thread. 12 13- Image processing: When large images need to be processed or complex image algorithms need to be executed, asynchronous work objects can ensure normal running of the main thread and improve the real-time performance of your application. 14 15You can use a promise or a callback to implement asynchronous calls. To use a callback, you must pass in the callback. 16 17 18 19## Example (Promise) 20 21 22 231. Use **napi_create_async_work** to create an asynchronous work object, and use **napi_queue_async_work** to add the object to a queue. 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 // Create an asynchronous work object. 51 napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB, callbackData, &callbackData->asyncWork); 52 // Add the asynchronous work object to a queue. 53 napi_queue_async_work(env, callbackData->asyncWork); 54 55 return promise; 56 } 57 ``` 58 592. Define the first callback of the asynchronous work object. This callback is executed in a worker thread to process specific service logic. 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. Define the second callback of the asynchronous work object. This callback is executed in the main thread to return the result to the ArkTS side. 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. Initialize the module and call the API of ArkTS. 89 90 ```cpp 91 // Initialize the module. 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 // Call the API of ArkTS. 102 nativeModule.asyncWork(1024).then((result) => { 103 hilog.info(0x0000, 'XXX', 'result is %{public}d', result); 104 } 105 ); 106 ``` 107 108## Example (Callback) 109 110 111 1121. Use **napi_create_async_work** to create an asynchronous work object, and use **napi_queue_async_work** to add the object to a queue. 113 114 ```cpp 115 struct CallbackData { 116 napi_async_work asyncWork = nullptr; 117 napi_ref callbackRef = nullptr; 118 double args[2] = {0}; 119 double result = 0; 120 }; 121 122 napi_value AsyncWork(napi_env env, napi_callback_info info) 123 { 124 size_t argc = 3; 125 napi_value args[3]; 126 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 127 auto asyncContext = new CallbackData(); 128 // Save the received parameters to callbackData. 129 napi_get_value_double(env, args[0], &asyncContext->args[0]); 130 napi_get_value_double(env, args[1], &asyncContext->args[1]); 131 napi_create_reference(env, args[2], 1, &asyncContext->callbackRef); 132 napi_value resourceName = nullptr; 133 napi_create_string_utf8(env, "asyncWorkCallback", NAPI_AUTO_LENGTH, &resourceName); 134 // Create an asynchronous work object. 135 napi_create_async_work(env, nullptr, resourceName, ExecuteCB, CompleteCB, 136 asyncContext, &asyncContext->asyncWork); 137 // Add the asynchronous work object to a queue. 138 napi_queue_async_work(env, asyncContext->asyncWork); 139 return nullptr; 140 } 141 ``` 142 1432. Define the first callback of the asynchronous work object. This callback is executed in a worker thread to process specific service logic. 144 145 ```cpp 146 static void ExecuteCB(napi_env env, void *data) 147 { 148 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 149 callbackData->result = callbackData->args[0] + callbackData->args[1]; 150 } 151 ``` 152 1533. Define the second callback of the asynchronous work object. This callback is executed in the main thread to return the result to the ArkTS side. 154 155 ```cpp 156 static void CompleteCB(napi_env env, napi_status status, void *data) 157 { 158 CallbackData *callbackData = reinterpret_cast<CallbackData *>(data); 159 napi_value callbackArg[1] = {nullptr}; 160 napi_create_double(env, callbackData->result, &callbackArg[0]); 161 napi_value callback = nullptr; 162 napi_get_reference_value(env, callbackData->callbackRef, &callback); 163 // Execute the callback. 164 napi_value result; 165 napi_value undefined; 166 napi_get_undefined(env, &undefined); 167 napi_call_function(env, undefined, callback, 1, callbackArg, &result); 168 // Delete the napi_ref object and asynchronous work object. 169 napi_delete_reference(env, callbackData->callbackRef); 170 napi_delete_async_work(env, callbackData->asyncWork); 171 delete callbackData; 172 } 173 ``` 174 1754. Initialize the module and call the API of ArkTS. 176 177 ```cpp 178 // Initialize the module. 179 static napi_value Init(napi_env env, napi_value exports) 180 { 181 napi_property_descriptor desc[] = { 182 { "asyncWork", nullptr, AsyncWork, nullptr, nullptr, nullptr, napi_default, nullptr } 183 }; 184 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 185 return exports; 186 } 187 188 // Call the API of ArkTS. 189 let num1: number = 123; 190 let num2: number = 456; 191 nativeModule.asyncWork(num1, num2, (result) => { 192 hilog.info(0x0000, 'XXX', 'result is %{public}d', result); 193 }); 194 ``` 195