1# Running or Stopping an Event Loop in an Asynchronous Thread Using Node-API Extensions 2 3## **Scenario** 4When calling asynchronous ArkTS APIs in the ArkTS running environment, you can use **napi_run_event_loop** to run an event loop and use **napi_stop_event_loop** to stop an event loop. 5 6## Example 7If asynchronous ArkTS APIs are called, you can use **napi_run_event_loop** to run the events in the asynchronous thread cyclically. The underlying asynchronous tasks in the event queue will be processed based on the event loop mode. Currently, Node-API provides two modes for running event loops: **napi_event_mode_nowait** and **napi_event_mode_default**. 8 9- If **napi_event_mode_nowait** is used, the current asynchronous thread will not be blocked while the system attempts to process a task in the underlying event queue. After the task is complete, the event loop stops. If there is no task in the event queue, the event loop stops immediately. 10- If **napi_event_mode_default** is used, the system blocks the current asynchronous thread and keeps trying to obtain tasks from the event queue and execute these tasks. If you do not want the current thread to be blocked, use **napi_stop_event_loop** to stop the event loop. 11 12### Sample Code 13- Register the module. 14 ```c++ 15 // hello.cpp 16 #include "napi/native_api.h" 17 #include <napi/common.h> 18 #include <pthread.h> 19 20 static napi_value ResolvedCallback(napi_env env, napi_callback_info info) 21 { 22 napi_stop_event_loop(env); 23 return nullptr; 24 } 25 26 static napi_value RejectedCallback(napi_env env, napi_callback_info info) 27 { 28 napi_stop_event_loop(env); 29 return nullptr; 30 } 31 32 static void *RunEventLoopFunc(void *arg) 33 { 34 // 1. Create an ArkTS instance. 35 napi_env env; 36 napi_status ret = napi_create_ark_runtime(&env); 37 if (ret != napi_ok) { 38 return nullptr; 39 } 40 41 // 2. Load the custom module. 42 napi_value objectUtils; 43 // 'com.example.myapplication' is the bundle name of the current application. 44 ret = napi_load_module_with_info(env, "ets/pages/ObjectUtils", "com.example.myapplication/entry", &objectUtils); 45 if (ret != napi_ok) { 46 return nullptr; 47 } 48 49 // 3. Call the asynchronous SetTimeout API. 50 napi_value setTimeout = nullptr; 51 napi_value promise = nullptr; 52 53 napi_get_named_property(env, objectUtils, "SetTimeout", &setTimeout); 54 napi_call_function(env, objectUtils, setTimeout, 0, nullptr, &promise); 55 56 napi_value theFunc = nullptr; 57 if (napi_get_named_property(env, promise, "then", &theFunc) != napi_ok) { 58 return nullptr; 59 } 60 61 napi_value resolvedCallback = nullptr; 62 napi_value rejectedCallback = nullptr; 63 napi_create_function(env, "resolvedCallback", NAPI_AUTO_LENGTH, ResolvedCallback, nullptr, &resolvedCallback); 64 napi_create_function(env, "rejectedCallback", NAPI_AUTO_LENGTH, RejectedCallback, nullptr, &rejectedCallback); 65 napi_value argv[2] = {resolvedCallback, rejectedCallback}; 66 napi_call_function(env, promise, theFunc, 2, argv, nullptr); 67 68 auto flag = reinterpret_cast<bool *>(arg); 69 if (*flag == true) { 70 napi_run_event_loop(env, napi_event_mode_default); 71 } else { 72 // Process the tasks in the event queue without blocking the asynchronous API. 73 napi_run_event_loop(env, napi_event_mode_nowait); 74 } 75 return nullptr; 76 } 77 78 static napi_value RunEventLoop(napi_env env, napi_callback_info info) 79 { 80 pthread_t tid; 81 size_t argc = 1; 82 napi_value argv[1] = { nullptr }; 83 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 84 85 bool flag = false; 86 napi_get_value_bool(env, argv[0], &flag); 87 // Create an asynchronous thread. 88 pthread_create(&tid, nullptr, RunEventLoopFunc, &flag); 89 pthread_join(tid, nullptr); 90 91 return nullptr; 92 } 93 94 // Register the module. 95 EXTERN_C_START 96 static napi_value Init(napi_env env, napi_value exports) 97 { 98 napi_property_descriptor desc[] = { 99 { "runEventLoop", nullptr, RunEventLoop, nullptr, nullptr, nullptr, napi_default, nullptr } 100 }; 101 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 102 return exports; 103 } 104 EXTERN_C_END 105 106 static napi_module nativeModule = { 107 .nm_version = 1, 108 .nm_flags = 0, 109 .nm_filename = nullptr, 110 .nm_register_func = Init, 111 .nm_modname = "entry", 112 .nm_priv = nullptr, 113 .reserved = { 0 }, 114 }; 115 116 extern "C" __attribute__((constructor)) void RegisterEntryModule() 117 { 118 napi_module_register(&nativeModule); 119 } 120 ``` 121 122- Declare the APIs. 123 ```ts 124 // index.d.ts 125 export const runEventLoop: (isDefault: boolean) => object; 126 ``` 127 128- Configure the compile settings. 1291. Configure the CMakeLists.txt file as follows: 130 ``` 131 // CMakeLists.txt 132 # the minimum version of CMake. 133 cmake_minimum_required(VERSION 3.4.1) 134 project(myapplication) 135 136 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 137 138 if(DEFINED PACKAGE_FIND_FILE) 139 include(${PACKAGE_FIND_FILE}) 140 endif() 141 142 include_directories(${NATIVERENDER_ROOT_PATH} 143 ${NATIVERENDER_ROOT_PATH}/include) 144 add_library(entry SHARED hello.cpp) 145 target_link_libraries(entry PUBLIC libace_napi.z.so) 146 ``` 1472. Add the following to the **build-profile.json5** file of the project. 148 ```json 149 { 150 "buildOption" : { 151 "arkOptions" : { 152 "runtimeOnly" : { 153 "sources": [ 154 "./src/main/ets/pages/ObjectUtils.ets" 155 ] 156 } 157 } 158 } 159 } 160 ``` 161- ArkTS sample code 162 ```ts 163 // index.ets 164 import testNapi from 'libentry.so' 165 166 testNapi.runEventLoop(true); 167 ``` 168 ```ts 169 // ets/pages/ObjectUtils.ets 170 export function SetTimeout() : Promise<void> { 171 return new Promise((resolve) => { 172 setTimeout(() => { 173 console.info('set timer delay 1s'); 174 // attempt to stop the event loop at napi terminal 175 resolve(); 176 }, 1000) 177 }) 178 } 179 ``` 180