【HarmonyOS NAPI 深度探索7】N-API 数据处理:与 JavaScript 数据的交互
【HarmonyOS NAPI 深度探索7】N-API 数据处理:与 JavaScript 数据的交互
在开发原生模块时,一个核心的需求就是与 JavaScript 数据交互。N-API 提供了丰富的工具,让你能够方便地处理各种类型的数据,从基础的字符串、数字到复杂的对象和数组。本文我们将通过实例化讲解如何在 N-API 中进行数据处理。
N-API 支持的基本数据类型
N-API 支持多种 JavaScript 数据类型的创建和操作,包括:
- 基本类型:如字符串、数字、布尔值等。
- 复合类型:如对象、数组、函数等。
- 特殊类型:如
Promise
、Buffer
、Date
等。
通过 N-API,可以轻松实现这些类型的互相转换和操作。
与 JavaScript 数据交互的基本操作
在 N-API 中,数据处理主要通过 Napi
命名空间提供的类和方法完成。下面通过几个具体示例来展示如何操作各种数据类型。
示例 1:处理字符串
字符串是最常用的数据类型之一。以下代码展示了如何在原生模块中接收字符串参数,并返回一个处理后的结果:
#include <napi.h>
Napi::String ProcessString(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 1 || !info[0].IsString()) {
Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException();
return Napi::String::New(env, "");
}
std::string input = info[0].As<Napi::String>();
std::string result = "Hello, " + input;
return Napi::String::New(env, result);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("processString", Napi::Function::New(env, ProcessString));
return exports;
}
NODE_API_MODULE(napi_example, Init)
运行以下测试代码:
const addon = require('./build/Release/napi_example');
console.log(addon.processString("HarmonyOS")); // 输出:Hello, HarmonyOS
这里主要通过Napi::String::New 创建TS字符串,然后返回给TS。
示例 2:处理数字
N-API 也可以用来接收和返回数字。例如,我们可以实现一个简单的加法函数:
Napi::Number AddNumbers(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
Napi::TypeError::New(env, "Two numbers expected").ThrowAsJavaScriptException();
return Napi::Number::New(env, 0);
}
double num1 = info[0].As<Napi::Number>().DoubleValue();
double num2 = info[1].As<Napi::Number>().DoubleValue();
return Napi::Number::New(env, num1 + num2);
}
通过以下代码测试:
const addon = require('./build/Release/napi_example');
console.log(addon.addNumbers(5, 3)); // 输出:8
示例 3:处理对象
N-API 允许你操作 JavaScript 对象,可以创建对象或访问和修改其属性:
Napi::Object CreateObject(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Object obj = Napi::Object::New(env);
obj.Set("name", "HarmonyOS");
obj.Set("version", 1.0);
return obj;
}
测试代码:
const addon = require('./build/Release/napi_example');
console.log(addon.createObject()); // 输出:{ name: 'HarmonyOS', version: 1 }
示例 4:处理数组
数组的操作同样简单,可以创建数组或访问其元素:
Napi::Array CreateArray(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Array arr = Napi::Array::New(env);
arr.Set(uint32_t(0), "Harmony");
arr.Set(uint32_t(1), "OS");
arr.Set(uint32_t(2), "NAPI");
return arr;
}
测试代码:
const addon = require('./build/Release/napi_example');
console.log(addon.createArray()); // 输出:[ 'Harmony', 'OS', 'NAPI' ]
示例 5:异步数据处理
N-API 也支持异步数据处理,可以通过 Promise
将原生操作结果返回到 JavaScript:
Napi::Value AsyncOperation(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::Promise::Deferred::New(env).Promise();
}
异步操作的具体实现可以结合线程池或事件循环完成。
napi.h与node_api.h
文本使用的api都是基于napi.h头文件提供的接口,napi.h依赖node_api.h,在HarmonyOS Next开发中用到node_api.h相关方法,后面会逐步介绍。这里简单说明一下两个头文件的区别。
- npai.h
- -
napi.h
是 Node.js 的 N - API(Node.js API for Native Modules)的头文件。N - API 是一个用于构建原生 Node.js 模块的稳定 ABI(Application Binary Interface)层。 - 它的主要目的是提供一个稳定的接口,使得原生模块可以在不同版本的 Node.js 运行时上无需重新编译就能工作。例如,当 Node.js 从版本 12 升级到版本 14 时,如果一个原生模块是使用 N - API 编写的(通过
napi.h
),只要该模块使用的 N - API 版本在两个 Node.js 版本中都受支持,就可以继续正常使用,而不需要修改和重新编译代码。 - N - API 抽象了 Node.js 的内部实现细节,开发者可以使用一组标准化的函数来操作 JavaScript 值、创建对象、调用函数等。例如,
napi_create_object
函数可以用于在原生代码中创建一个 JavaScript 对象,这种操作方式在不同的 Node.js 版本中是相对稳定的。
- -
- node_api.h
node_api.h
在早期的 Node.js 原生模块开发中被使用。它与napi.h
相比,没有提供像 N - API 那样稳定的 ABI。- 其接口与 Node.js 内部的 JavaScript 运行时(如 V8 引擎)的联系更紧密,并且可能会因为 Node.js 内部实现的变化而发生改变。例如,在 Node.js 版本升级过程中,如果 V8 引擎的某些底层接口发生了修改,使用
node_api.h
编写的原生模块可能需要进行相应的调整和重新编译才能继续正常工作。
在napi项目中napi.h头文件位于node_modules下面:
总结
N-API 提供了一套强大的 API,支持与 JavaScript 各种数据类型的交互。无论是字符串、数字这样的简单类型,还是对象、数组这样的复杂类型,甚至是异步数据处理,N-API 都能轻松应对。通过这些工具,你可以将复杂的底层逻辑封装到原生模块中,并在 JavaScript 中方便地调用它们。