鸿蒙HarmonyOS代码开发:Node-API开发总结

获取JS传入参数及其数量

【规则】 当传入napi_get_cb_info的argv不为nullptr时,argv的长度必须大于等于传入argc声明的大小。

当argv不为nullptr时,napi_get_cb_info会根据argc声明的数量将JS实际传入的参数写入argv。如果argc小于等于实际JS传入参数的数量,该接口仅会将声明的argc数量的参数写入argv;而当argc大于实际参数数量时,该接口会在argv的尾部填充undefined。

错误示例

static napi_value IncorrectDemo1(napi_env env, napi_callback_info info) {
    // argc 未正确的初始化,其值为不确定的随机值,导致 argv 的长度可能小于 argc 声明的数量,数据越界。
    size_t argc;
    napi_value argv[10] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
    return nullptr;
}

static napi_value IncorrectDemo2(napi_env env, napi_callback_info info) {
    // argc 声明的数量大于 argv 实际初始化的长度,导致 napi_get_cb_info 接口在写入 argv 时数据越界。
    size_t argc = 5;
    napi_value argv[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
    return nullptr;
}

正确示例

static napi_value GetArgvDemo1(napi_env env, napi_callback_info info) {
    size_t argc = 0;
    // argv 传入 nullptr 来获取传入参数真实数量
    napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
    // JS 传入参数为0,不执行后续逻辑
    if (argc == 0) {
        return nullptr;
    }
    // 创建数组用以获取JS传入的参数
    napi_value* argv = new napi_value[argc];
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
    // 业务代码
    // ... ...
    // argv 为 new 创建的对象,在使用完成后手动释放
    delete argv;
    return nullptr;
}

static napi_value GetArgvDemo2(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value argv[2] = {nullptr};
    // napi_get_cb_info 会向 argv 中写入 argc 个 JS 传入参数或 undefined
    napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
    // 业务代码
    // ... ...
    return nullptr;
}

生命周期管理

【规则】 合理使用napi_open_handle_scope和napi_close_handle_scope管理napi_value的生命周期,做到生命周期最小化,避免发生内存泄漏问题。

每个napi_value属于特定的HandleScope,HandleScope通过napi_open_handle_scope和napi_close_handle_scope来建立和关闭,HandleScope关闭后,所属的napi_value就会自动释放。

正确示例

// 在for循环中频繁调用napi接口创建js对象时,要加handle_scope及时释放不再使用的资源。
// 下面例子中,每次循环结束局部变量res的生命周期已结束,因此加scope及时释放其持有的js对象,防止内存泄漏
for (int i = 0; i < 100000; i++) {
    napi_handle_scope scope = nullptr;
    napi_open_handle_scope(env, &scope);
    if (scope == nullptr) {
        return;
    }
    napi_value res;
    napi_create_object(env, &res);
    napi_close_handle_scope(env, scope);
}

上下文敏感

【规则】 多引擎实例场景下,禁止通过Node-API跨引擎实例访问JS对象。

引擎实例是一个独立运行环境,JS对象创建访问等操作必须在同一个引擎实例中进行。若在不同引擎实例中操作同一个对象,可能会引发程序崩溃。引擎实例在接口中体现为napi_env。

错误示例

// 线程1执行,在env1创建string对象,值为"bar"、
napi_create_string_utf8(env1, "bar", NAPI_AUTO_LENGTH, &string);
// 线程2执行,在env2创建object对象,并将上述的string对象设置到object对象中
napi_status status = napi_create_object(env2, &object);
if (status != napi_ok) {
    napi_throw_error(env, ...);
    return;
}

status = napi_set_named_property(env2, object, "foo", string);
if (status != napi_ok) {
    napi_throw_error(env, ...);
    return;
}

所有的JS对象都隶属于具体的某一napi_env,不可将env1的对象,设置到env2中的对象中。在env2中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值