您现在的位置是:亿华云 > IT科技
OpenHarmony 源码解析之JavaScript API框架(NAPI)
亿华云2025-10-09 01:22:23【IT科技】7人已围观
简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com1.NAPI概念1.1 JS API概念JS API: JavaScript Applic
想了解更多内容,码解请访问:
和华为官方合作共建的码解鸿蒙技术社区
https://harmonyos.51cto.com
1.NAPI概念
1.1 JS API概念
JS API: JavaScript Application Programming Interface, JavaScript应用程序编程接口。
1.2 JS API实现方式
OpenHarmony上JS API实现方式有三种,码解分别是码解:JSI机制、Channel机制、码解NAPI机制。码解
JSI机制:L0~L1设备支持。码解
Channel机制:L3设备支持。码解
NAPI机制:目前仅L2设备支持,码解后续须推广到L3~L5设备。码解

1.3 NAPI概念
一句话概括NAPI,码解就是码解L2设备上的 JS API实现方式。
2.NAPI机制介绍
2.1 实现原则
优先封装异步方法!同步方法可待社区反馈需要时再行添加。码解
若引擎开启Promise特性支持,码解则异步方法必须同时支持Callback方式和Promise方式。码解使用哪种方式由应用开发者决定,以是否传递Callback进行区分。不传递Callback即为Promise方式,方法执行结果为Promise实例对象。
L0到L1设备上受限于硬件水平,只实现Callback方式的异步方法; L2到L5设备上,必须实现同时支持Callback方式和Promise方式的异步方法。2.2 异步编程模型
2.2.1Promise 异步模型
Promise 异步模型是 OHOS 标准异步模型之一。
Promise对象: ES6原生提供了Promise对象,Promise是异步编程的b2b信息网一种解决方案,可以替代传统的解决方案–回调函数和事件。promise对象是一个异步操作的结果,提供了一些API使得异步执行可以按照同步的流表示出来,避免了层层嵌套的回调函数,保证了回调是以异步的方式进行调用的。用户在调用这些接口的时候,接口实现将异步执行任务,同时返回一个 Promise 对象,其代表异步操作的结果。在返回的结果的个数超过一个时,其以对象属性的形式返回。
Promise特点 作为对象,Promise有两个特点:(1)对象的状态不受外界影响;(2)一旦状态改变了就不会再变,也就是说任何时候Promise都只有一种状态。
2.2.2Callback 异步模型
Callback 异步模型是 OHOS 标准异步模型之一。用户在调用这些接口的时候,接口实现将异步执行任务。免费信息发布网任务执行结果以参数的形式提供给用户注册的回调函数。这些参数的第一个是 Error 或 undefined 类型,分别表示执行出错与正常。
2.2 实现步骤
2.2.1 模块注册
API集合按业务功能进行模块划分。开发者使用前须import对应的模块。
命名:@ohos.模块名
注意:
模块名须唯一,由ACE团队统一维护,子系统新增模块时须向ACE团队申请。 模块名最好是单个名词。实在不行,也可以由多个名词组成,但必须遵循小驼峰命名规则。 一个模块,一个声明文件(*.d.ts)。声明文件命名遵循@ohos.模块名.d.ts,文件名全小写,单词间无分割。N-API通过注册函数进行模块的注册,其接受一个全局变量参数,全局变量结构体中定义了模块名及模块初始化函数。在模块的初始化中,我们可以定义模块需要暴露的方法及属性。
示例:
static napi_value StorageExport(napi_env env, napi_value exports) { const char* storageClassName = "Storage"; napi_value storageClass = nullptr; /* 定义模块需要对外暴露的方法 */ static napi_property_descriptor storageDesc[] = { DECLARE_NAPI_FUNCTION("get", JSStorageGet), DECLARE_NAPI_FUNCTION("getSync", JSStorageGetSync), }; /* 定义C++类对应的亿华云JavaScript类,包括JS类名、JS构造函数 */ napi_define_class(env, storageClassName, strlen(storageClassName), JSStorageConstructor, nullptr, sizeof(storageDesc) / sizeof(storageDesc[0]), storageDesc, &storageClass); /* 定义模块需要对外暴露的属性 */ static napi_property_descriptor desc[] = { DECLARE_NAPI_PROPERTY("Storage", storageClass), }; /* 设置exports对象属性 */ napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; }模块定义
static napi_module storageModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = StorageExport, .nm_modname = "storage", .nm_priv = ((void*)0), .reserved = { 0 }, };模块注册
extern "C" __attribute__((constructor)) void StorageRegister() { napi_module_register(&storageModule); }2.2.2 NAPI声明
声明文件模板
@ohos.模块名.d.ts文件:
/** * 模块描述 * @since API版本号,IT Release3 对应 4,以此类推 * @sysCap 系统能力 * @devices 支持设备 * @import 导入模块 * @permission 权限列表 */ declare namespace 模块名 { // 在此处定义功能方法 } export default 模块名;示例:
声明文件@ohos.storage.d.ts
/** * 存储 * @since 3 * @sysCap ACE Engine * @devices phone, tablet, tv, wearable, liteWearable, smartVision * @import import storage from @ohos.storage; * @permission N/A */ declare namespace storage { // 在此处定义功能方法 } export default storage;2.2.2 NAPI实现
JS API 调用流程如下图所示:

接口定义
/**入参** napi_env:表示一个上下文的变量; napi_callback_info:传递给回调函数的一个封装的数据类型,可以用于获取有关调用时的上下文信息,也可以用于设置回调函数的返回值; **返回值** napi_value:对所有js的基本值的一个密闭封装,就是表示一个基本值; */ static napi_value Get(napi_env env, napi_callback_info info); static napi_value GetSync(napi_env env, napi_callback_info info);2.2.2.1 同步回调
同步方法调用之后,将阻塞住JS线程直至获取到返回值。
命名:动词+Sync或动词+名词+Sync
格式:
无参:方法名() 有参:方法名Sync(必填参数[, 可选参数])返回值
有声明文件模板
declare namespace 模块名 { /** * 方法描述 * @note 特殊说明 * @since (可选,方法支持版本与模块不一致时需标明) * @sysCap 系统能力 * @devices 支持设备 (可选,支持设备类型与模块不一致时需标明) * @param 参数 参数说明(可选,没有参数或参数用interface包含时不需要标明) * @return 返回值说明(可选,没有返回值或返回值用interface包含时不需要标明) */ // 无参 function 方法名Sync(): 返回值类型; // 有参 function 方法名Sync(必填参数: 参数类型, options?: 可选参数类型): 返回值类型; interface 可选参数类型 { 参数名: 参数类型; } } export default 模块名;示例
声明
declare namespace storage { /** * getSync方法描述 * @since 6 * @sysCap ACE Enginge * @param key key值说明 * @return 返回值说明 */ function getSync(key: string, options?: GetStorageOptions): string; interface GetStorageOptions { /** * default参数描述 * @since 6 * @sysCap ACE Enginge */ default: string; } } export default storage;实现
static napi_value GetSync(napi_env env, napi_callback_info info) { size_t requireArgc = 1; size_t argc = 2; //参数个数 napi_value argv[2] = { 0 }; //参数定义 napi_value thisVar = nullptr; //JS对象的this参数 void* data = nullptr; //回调数据指针 /* 根据环境变量获取参数 */ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); NAPI_ASSERT(env, argc >= requireArgc, "requires 1 parameter"); char key[KEY_BUFFER_SIZE] = { 0 }; size_t keyLen = 0; char value[VALUE_BUFFER_SIZE] = { 0 }; size_t valueLen = 0; for (size_t i = 0; i < argc; i++) { napi_valuetype valueType = napi_undefined; napi_typeof(env, argv[i], &valueType); if (i == 0 && valueType == napi_string) { /* 根据JS字符串获取对应的UTF8编码格式的C/C++字符串 */ napi_get_value_string_utf8(env, argv[i], key, KEY_BUFFER_SIZE, &keyLen); } else if (i == 1 && valueType == napi_string) { napi_get_value_string_utf8(env, argv[i], value, VALUE_BUFFER_SIZE, &valueLen); break; } else { NAPI_ASSERT(env, false, "type mismatch"); } } StorageObjectInfo* objectInfo = nullptr; /* 根据JS对象获取与之绑定的原生对象实例 */ napi_unwrap(env, thisVar, (void**)&objectInfo); auto itr = g_keyValueStorage.find(key); napi_value result = nullptr; // JS字符串对象 if (itr != g_keyValueStorage.end()) { /* 根据UTF8编码格式的 C/C++字符串 创建一个 JS字符串对象 */ napi_create_string_utf8(env, itr->second.c_str(), itr->second.length(), &result); } else if (valueLen > 0) { napi_create_string_utf8(env, value, valueLen, &result); } else { objectInfo->Emit(nullptr, "error"); NAPI_ASSERT(env, false, "key does not exist"); } return result; //返回JS对象 }2.2.2.2 异步回调
异步方法调用整个过程不会阻碍调用者的工作。
命名:动词或动词+名词
格式:
无参:方法名([回调函数]) 有参:方法名(必填参数[, 可选参数][, 回调函数])返回值
若回调函数非空,则返回void 若回调函数为空,则返回Promise实例对象声明文件模板
declare namespace 模块名 { /** * 方法描述 * @note 特殊说明 * @since (可选,方法支持版本与模块不一致时需标明) * @sysCap 系统能力 * @devices 支持设备 (可选,支持设备类型与模块不一致时需标明) * @param 参数 参数说明(可选,没有参数或参数用interface包含时不需要标明) */ // 无参 function 方法名(callback: AsyncCallback<结果数据类型>): void; function 方法名(): Promise<结果数据类型>; // 有参 function 方法名(必填参数: 参数类型, callback: AsyncCallback<结果数据类型>): void; function 方法名(必填参数: 参数类型, options: 可选参数类型, callback: AsyncCallback<结果数据类型>): void; function 方法名(必填参数: 参数类型, options?: 可选参数类型): Promise<结果数据类型>; interface 可选参数类型 { 参数名: 参数类型; } } export default 模块名;示例:
声明
import { AsyncCallback } from ./basic; declare namespace storage { /** * get方法描述 * @note N/A * @since 5 * @sysCap ACE Engine * @devices phone, tablet, tv, wearable * @param key key值说明 */ function get(key: string, callback: AsyncCallback<string>): void; function get(key: string, options: GetStorageOptions, callback: AsyncCallback<string>): void; function get(key: string, options?: GetStorageOptions): Promise<string>; interface GetStorageOptions { default: string; } } export default storage;实现
异步回调流程如下图所示:

3. 应用代码示例
JS应用引用NAPI接口时,须先引用接口定义的对应模块,才能进行接口的调用。
import storage from @ohos.storage export default { testGetSync() { //同步接口 var name = storage.getSync(name); console.log(name is + name); }, testGet() { //异步接口 storage.get(name) .then(date => console.log(name is + data) ) .catch(error => console.log(error: + error) ); } }想了解更多内容,请访问:
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com
很赞哦!(98)