1# Node-API常见问题 2 3## ArkTS/JS侧import xxx from libxxx.so后,使用xxx报错显示undefined/not callable 4 51. 排查.cpp文件在注册模块时的模块名称与so的名称匹配一致。 6 如模块名为entry,则so的名字为libentry.so,napi_module中nm_modname字段应为entry,大小写与模块名保持一致。 7 82. 排查so是否加载成功。 9 应用启动时过滤模块加载相关日志,重点搜索"dlopen"关键字,确认是否有相关报错信息;常见加载失败原因有权限不足、so文件不存在以及so已拉入黑名单等,可根据以下关键错误日志确认问题。其中,多线程场景(worker、taskpool等)下优先检查模块实现中nm_modname是否与模块名一致,区分大小写。 10 113. 排查依赖的so是否加载成功。 12 确定所依赖的其它so是否打包到应用中以及是否有权限打开。常见加载失败原因有权限不足、so文件不存在等,可根据以下关键错误日志确认问题。 13 144. 排查模块导入方式与so路径是否对应。 15 若JS侧导入模块的形式为: import xxx from '\@ohos.yyy.zzz',则该so将在/system/lib/module/yyy中找libzzz.z.so或libzzz_napi.z.so,若so不存在或名称无法对应,则报错日志中会出现dlopen相关日志。 16 17 注意,32位系统路径为/system/lib,64位系统路径为/system/lib64。 18 19| **已知关键错误日志** | **修改建议** | 20| -------- | -------- | 21| module $SO is not allowed to load in restricted runtime | $SO表示模块名。该模块不在受限worker线程的so加载白名单,不允许加载,建议用户删除该模块。 | 22| module $SO is in blocklist, loading prohibited | $SO表示模块名。受卡片或者Extension管控,该模块在黑名单内,不允许加载,建议用户删除该模块。 | 23| load module failed. $ERRMSG | 动态库加载失败。$ERRMSG表示加载失败原因,一般常见原因是so文件不存在、依赖的so文件不存在或者符号未定义,需根据加载失败原因具体分析。 | 24| try to load abc file from $FILEPATH failed. | 通常加载动态库和abc文件为二选一:如果是要加载动态库并且加载失败,该告警可以忽略;如果是要加载abc文件,则该错误打印的原因是abc文件不存在,$FILEPATH表示模块路径。 | 25 26## 接口执行结果非预期,日志显示occur exception need return 27 28部分Node-API接口在调用结束前会进行检查,检查虚拟机中是否存在JS异常。如果存在异常,则会打印出occur exception need return日志,并打印出检查点所在的行号,以及对应的Node-API接口名称。 29 30解决此类问题有以下两种思路: 31 32- 若该异常开发者不关心,可以选择直接清除。 33 可直接使用napi接口napi_get_and_clear_last_exception,清理异常。调用时机:在打印occur exception need return日志的接口之前调用。 34 35- 将该异常继续向上抛到ArkTS层,在ArkTS层进行捕获。 36 发生异常时,可以选择走异常分支, 确保不再走多余的Native逻辑 ,直接返回到ArkTS层。 37 38## napi_value和napi_ref的生命周期有何区别 39 40- native_value由HandleScope管理,一般开发者不需要自己加HandleScope(uv_queue_work的complete callback除外)。 41 42- napi_ref由开发者自己管理,需要手动delete。 43 44## Node-API接口返回值不是napi_ok时,如何排查定位 45 46Node-API接口正常执行后,会返回一个napi_ok的状态枚举值,若napi接口返回值不为napi_ok,可从以下几个方面进行排查。 47 48- Node-API接口执行前一般会进行入参校验,首先进行的是判空校验。在代码中体现为: 49 50 ```cpp 51 CHECK_ENV: env判空校验 52 CHECK_ARG:其它入参判空校验 53 ``` 54 55- 某些Node-API接口还有入参类型校验。比如napi_get_value_double接口是获取JS number对应的C double值,首先就要保证的是:JS value类型为number,因此可以看到相关校验。 56 57 ```cpp 58 RETURN_STATUS_IF_FALSE(env, nativeValue->TypeOf() == NATIVE_NUMBER, napi_number_expected); 59 ``` 60 61- 还有一些接口会对其执行结果进行校验。比如napi_call_function这个接口,其功能是执行一个JS function,当JS function中出现异常时,Node-API将会返回napi_pending_exception的状态值。 62 63 ```cpp 64 auto resultValue = engine->CallFunction(nativeRecv, nativeFunc, nativeArgv, argc); 65 RETURN_STATUS_IF_FALSE(env, resultValue != nullptr, napi_pending_exception) 66 ``` 67 68- 还有一些状态值需要根据相应Node-API接口具体分析:确认具体的状态值,分析这个状态值在什么情况下会返回,再排查具体出错原因。 69