# 使用扩展的Node-API接å£åœ¨å¼‚æ¥çº¿ç¨‹ä¸è¿è¡Œå’Œåœæ¢äº‹ä»¶å¾ªçޝ ## åœºæ™¯ä»‹ç» å¼€å‘者在自己创建的ArkTSè¿è¡ŒçŽ¯å¢ƒä¸è°ƒç”¨å¼‚æ¥çš„ArkTSæŽ¥å£æ—¶ï¼Œå¯ä»¥é€šè¿‡ä½¿ç”¨Node-APIä¸çš„æ‰©å±•接å£napi_run_event_loopå’Œnapi_stop_event_loopæ¥è¿è¡Œå’Œåœæ¢ArkTS实例ä¸çš„事件循环。 ## 调用异æ¥çš„ArkTS接å£ç¤ºä¾‹ 调用的ArkTS接å£ä¸ºå¼‚æ¥æŽ¥å£æ—¶ï¼Œéœ€è¦é€šè¿‡æ‰©å±•接å£napi_run_event_loop将异æ¥çº¿ç¨‹ä¸çš„事件循环è¿è¡Œèµ·æ¥ï¼Œåº•层事件队列ä¸çš„异æ¥ä»»åŠ¡å°†è¢«å¤„ç†æ‰§è¡Œã€‚当å‰Node-API扩展了两ç§äº‹ä»¶å¾ªçŽ¯æ¨¡å¼æ¥è¿è¡Œå¼‚æ¥çº¿ç¨‹çš„事件循环,分别为napi_event_mode_nowait模å¼å’Œnapi_event_mode_default模å¼ã€‚ 如果使用napi_event_mode_nowait模å¼è¿è¡Œåº•层事件循环,系统会å°è¯•从底层的事件队列ä¸å–出一个任务并处ç†ï¼Œå®Œæˆä¹‹åŽäº‹ä»¶å¾ªçŽ¯åœæ¢ï¼Œå¦‚æžœåº•å±‚çš„äº‹ä»¶é˜Ÿåˆ—ä¸æ²¡æœ‰ä»»åŠ¡ï¼Œäº‹ä»¶å¾ªçŽ¯ä¼šç«‹åˆ»åœæ¢ï¼Œå½“å‰çš„异æ¥çº¿ç¨‹ä¸ä¼šè¢«é˜»å¡žï¼› 如果使用napi_event_mode_defaultæ¨¡å¼æ¥è¿è¡Œåº•层事件循环,系统会阻塞当å‰çš„çº¿ç¨‹ï¼ŒåŒæ—¶ä¼šä¸€ç›´å°è¯•从事件队列ä¸èŽ·å–任务并执行处ç†è¿™äº›ä»»åŠ¡ã€‚å¦‚æžœä¸æƒ³å½“å‰çº¿ç¨‹ç»§ç»è¢«é˜»å¡žï¼Œå¯ä»¥ä½¿ç”¨æ‰©å±•接å£napi_stop_event_loopå°†æ£åœ¨è¿è¡Œçš„äº‹ä»¶å¾ªçŽ¯åœæ¢ã€‚ ### 示例代ç - æ¨¡å—æ³¨å†Œ ```c++ // hello.cpp #include "napi/native_api.h" #include <napi/common.h> #include <pthread.h> static napi_value ResolvedCallback(napi_env env, napi_callback_info info) { napi_stop_event_loop(env); return nullptr; } static napi_value RejectedCallback(napi_env env, napi_callback_info info) { napi_stop_event_loop(env); return nullptr; } static void *RunEventLoopFunc(void *arg) { // 1. 创建ArkTS实例 napi_env env; napi_status ret = napi_create_ark_runtime(&env); if (ret != napi_ok) { return nullptr; } // 2. åŠ è½½è‡ªå®šä¹‰çš„æ¨¡å— napi_value objectUtils; // 'com.example.myapplication' 为当å‰åº”用的bundleName ret = napi_load_module_with_info(env, "ets/pages/ObjectUtils", "com.example.myapplication/entry", &objectUtils); if (ret != napi_ok) { return nullptr; } // 3. 调用异æ¥SetTimeoutæŽ¥å£ napi_value setTimeout = nullptr; napi_value promise = nullptr; napi_get_named_property(env, objectUtils, "SetTimeout", &setTimeout); napi_call_function(env, objectUtils, setTimeout, 0, nullptr, &promise); napi_value theFunc = nullptr; if (napi_get_named_property(env, promise, "then", &theFunc) != napi_ok) { return nullptr; } napi_value resolvedCallback = nullptr; napi_value rejectedCallback = nullptr; napi_create_function(env, "resolvedCallback", NAPI_AUTO_LENGTH, ResolvedCallback, nullptr, &resolvedCallback); napi_create_function(env, "rejectedCallback", NAPI_AUTO_LENGTH, RejectedCallback, nullptr, &rejectedCallback); napi_value argv[2] = {resolvedCallback, rejectedCallback}; napi_call_function(env, promise, theFunc, 2, argv, nullptr); auto flag = reinterpret_cast<bool *>(arg); if (*flag == true) { napi_run_event_loop(env, napi_event_mode_default); } else { // éžé˜»å¡žå¼çš„处ç†ä»»åŠ¡ï¼Œæœ‰å¯èƒ½é˜Ÿåˆ—ä¸è¿˜æ²¡æœ‰ä»»åС就已ç»è¿”回了 napi_run_event_loop(env, napi_event_mode_nowait); } return nullptr; } static napi_value RunEventLoop(napi_env env, napi_callback_info info) { pthread_t tid; size_t argc = 1; napi_value argv[1] = { nullptr }; napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); bool flag = false; napi_get_value_bool(env, argv[0], &flag); // 创建异æ¥çº¿ç¨‹ pthread_create(&tid, nullptr, RunEventLoopFunc, &flag); pthread_join(tid, nullptr); return nullptr; } // æ³¨å†Œæ¨¡å—æŽ¥å£ EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { { "runEventLoop", nullptr, RunEventLoop, nullptr, nullptr, nullptr, napi_default, nullptr } }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END static napi_module nativeModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "entry", .nm_priv = nullptr, .reserved = { 0 }, }; extern "C" __attribute__((constructor)) void RegisterEntryModule() { napi_module_register(&nativeModule); } ``` - 接å£å£°æ˜Ž ```ts // index.d.ts export const runEventLoop: (isDefault: boolean) => object; ``` - 编译é…ç½® 1. CMakeLists.txtæ–‡ä»¶éœ€è¦æŒ‰ç…§å¦‚下é…ç½® ``` // CMakeLists.txt # the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(myapplication) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) if(DEFINED PACKAGE_FIND_FILE) include(${PACKAGE_FIND_FILE}) endif() include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) add_library(entry SHARED hello.cpp) target_link_libraries(entry PUBLIC libace_napi.z.so) ``` 2. 需è¦åœ¨å·¥ç¨‹çš„build-profile.json5文件ä¸è¿›è¡Œä»¥ä¸‹é…ç½® ```json { "buildOption" : { "arkOptions" : { "runtimeOnly" : { "sources": [ "./src/main/ets/pages/ObjectUtils.ets" ] } } } } ``` - ArkTS代ç 示例 ```ts // index.ets import testNapi from 'libentry.so' testNapi.runEventLoop(true); ``` ```ts // ets/pages/ObjectUtils.ets export function SetTimeout() : Promise<void> { return new Promise((resolve) => { setTimeout(() => { console.info('set timer delay 1s'); // attempt to stop the event loop at napi terminal resolve(); }, 1000) }) } ```