承接上文,与callback方式不同的是,promise对象由C++侧创建以返回值的方式传递回js/ets侧,promise对象存储异步执行的结果。
// foundation/filemanagement/file_api/interfaces/kits/js/src/common/napi/n_async/n_async_work_promise.cpp
NVal NAsyncWorkPromise::Schedule(string procedureName, NContextCBExec cbExec, NContextCBComplete cbComplete)
{
ctx_->cbExec_ = move(cbExec);
ctx_->cbComplete_ = move(cbComplete);
napi_status status;
napi_value result = nullptr;
status = napi_create_promise(env_, &ctx_->deferred_, &result);
if (status != napi_ok) {
HILOGE("INNER BUG. Cannot create promise for %{public}d", status);
return NVal();
}
napi_value resource = NVal::CreateUTF8String(env_, procedureName).val_;
status = napi_create_async_work(env_, nullptr, resource, PromiseOnExec, PromiseOnComplete, ctx_, &ctx_->awork_);
if (status != napi_ok) {
HILOGE("INNER BUG. Failed to create async work for %{public}d", status);
return NVal();
}
status = napi_queue_async_work(env_, ctx_->awork_);
if (status != napi_ok) {
HILOGE("INNER BUG. Failed to queue async work for %{public}d", status);
return NVal();
}
ctx_ = nullptr; // The ownership of ctx_ has been transfered
return { env_, result };
}
1.napi_create_promise创建创建Promise,返回promise、deferred 二个对象, promise用于主线程方法返回。 deferred对象用于resolve、reject处理。
首先先分析下napi_create_promise的方法定义
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise);
参数说明:
[in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。
[out] deferred: 返回接收刚创建的deferred对象,关联Promise对象,后面用于napi_resolve_deferred() 或 napi_reject_deferred() 更新状态,返回数据。
[out] promise: 关联上面deferred对象的JS Promise对象,用于主线程方法返回。
返回值:返回napi_ok表示转换成功,其他值失败。
2.执行napi_create_async_work异步线程后,将deferred对象,通过napi_queue_async_work将创建的async work添加到队列,由NAPI框架的底层去调度后执行。
3.result即为返回的promise对象。
napi_create_async_work中的异步处理execute和complete方法,分别对应PromiseOnExec, PromiseOnComplete。处理完成后将ctx->res_结果更新至deferred的对象中。
static void PromiseOnExec(napi_env env, void *data)
{
...
}
static void PromiseOnComplete(napi_env env, napi_status status, void *data)
{
...
if (!ctx->res_.TypeIsError(true)) {
napi_status status = napi_resolve_deferred(env, ctx->deferred_, ctx->res_.val_);
if (status != napi_ok) {
HILOGE("Internal BUG, cannot resolve promise for %{public}d", status);
}
} else {
napi_status status = napi_reject_deferred(env, ctx->deferred_, ctx->res_.val_);
if (status != napi_ok) {
HILOGE("Internal BUG, cannot reject promise for %{public}d", status);
}
}
ctx->deferred_ = nullptr;
napi_delete_async_work(env, ctx->awork_);
delete ctx;
}
最终返回临时结果NVal给js调用 (callback接口返回的是void, promise接口返回的是返回临时结果给js调用)。
此文讲解NAPI选用的分布式文件子系统,此实例将NAPI的接口封装成了多个操作的类(NAsyncWorkPromise、NAsyncWorkCallback、NVal等),对JS如何通过NAPI的调用C++调用流程与使用方式有一定的了解。如果想了解更多的NAPI的使用细节,可以在Openharmony的其它的子系统中查看其它的NAPI方法。以下提供NAPI的其它的一些接口说明和注意事项。
typedef enum {
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
napi_bigint
} napi_valuetype;
//对应了ECMAScript标准中定义的Undefined、Null、Boolean、Number、String、Symbol、Object、Function和BigInt九种数据类型。另外,napi_valuetype还包括了一个napi_external类型,其表示没有任何属性也没有任何原型的对象。
napi_status napi_get_value_double(
napi_env env,
napi_value value, // 获取的Javascript值
double *result // 用于保存对应的double类型值
);
// napi_create_double创建其对应的Javascript double值result
napi_status napi_create_double(
napi_env env,
double value, // double类型的值
napi_value *result // 保存创建的Javascript值
);
// napi_create_string_utf8用于创建一个UTF-8类型的字符串对象,其值来自于参数传递的UTF-8编码字符串
napi_status napi_create_string_utf8(napi_env env,
const char *str,
size_t length,
napi_value* result
);
napi_status napi_get_value_double(
napi_env env,
napi_value value, // 获取的Javascript值
double *result // 用于保存对应的double类型值
);
// napi_create_double创建其对应的Javascript double值result
napi_status napi_create_double(
napi_env env,
double value, // double类型的值
napi_value *result // 保存创建的Javascript值
);
// napi_create_string_utf8用于创建一个UTF-8类型的字符串对象,其值来自于参数传递的UTF-8编码字符串
napi_status napi_create_string_utf8(napi_env env,
const char *str,
size_t length,
napi_value* result
);
// C/C++类型转NAPI类型
napi_status napi_create_object(napi_env env, napi_value *value);
napi_status napi_create_array(napi_env env, napi_value* value);
//异步方法需要在不同线程中传递各种业务数据,定义一个结构体保存这些被传递的信息
struct MyAsyncContext {
napi_env env = nullptr; // napi运行环境
napi_async_work work = nullptr; // 异步工作对象
napi_deferred deferred = nullptr; // 延迟执行对象(用于promise方式返回计算结果)
napi_ref callbackRef = nullptr; // js callback function的引用对象 (用于callback方式返回计算结果)
int32_t status;
napi_value value[3];
};
其它一些API参考官方文档:
https://www.apiref.com/nodejs-zh/n-api.html
1.回调函数callback字段使用napi_ref类型,不能使用napi_value类型。因napi_value类型对象生命周期在原生方法结束时结束,导致在work线程、EventLoop线程中获取不到,而napi_ref类型生命周期大于方法的。
2.NAPI在Openharmony的V3.2版本之后,添加了NAPI框架生成工具(napi_generator)子系统,故名思义,可以自动生成NAPI的框架,后续如果有读者对此有兴趣,可以专门开辟篇章进行说明。
1.关于service ability的前世今生
2.L0设备在Openharmony基座上的开发实例
3.鸿蒙编译构建流程