1# 使用JSVM-API接口处理异步操作 2<!--Kit: NDK Development--> 3<!--Subsystem: arkcompiler--> 4<!--Owner: @yuanxiaogou; @string_sz--> 5<!--Designer: @knightaoko--> 6<!--Tester: @test_lzz--> 7<!--Adviser: @fang-jinxu--> 8 9## 简介 10 11使用JSVM-API接口处理异步操作。异步操作是指需要一定时间才能完成的操作,例如从网络下载数据或读取大型文件。与同步操作不同,异步操作不会阻塞主线程,而是会在后台执行。当异步操作完成后,事件循环将把它放入任务队列中,等待主线程空闲时执行。 12 13## 基本概念 14 15Promise是JavaScript中用来处理异步操作的对象,Promise有pending(待定)、fulfilled(已兑现)和rejected(已拒绝)三种状态,Promise的初始状态是pending,resolve函数可以使其状态从pending变为fulfilled(已兑现),reject函数可以使其状态从pending变为rejected(已拒绝),一旦兑现或拒绝Promise的状态将不能更改。下面是一些基本概念: 16 17- **同步**: 同步是指代码按照顺序一行一行地执行,每行代码的执行都会等待上一行代码执行完成后再继续执行。在同步执行中,如果某个操作需要花费较长时间,那么整个程序的执行就会被阻塞,直到该操作完成才能继续执行后续代码。 18- **异步**:异步是指任务可以同时执行,不需要等待上一个任务结束。在JavaScript中,常见的异步操作包括定时器、事件监听、网络请求等。异步任务不会阻塞后续任务的执行,而是通过回调函数或Promise对象来处理任务的结果。 19- **Promise**:Promise是一个JavaScript对象,用于处理异步操作。Promise作用于外部,通常通过then、catch和finally方法暴露给外部以添加自定义逻辑。 20- **deferred**:deferred是延迟对象,它可以与Promise对象关联,设置Promise的回调函数resolve和reject。deferred作用于内部,维护异步模型的状态并设置回调函数resolve和reject。 21- **resolve**:此函数可以将Promise的状态从pending(待定)改为fulfilled(已兑现),向resolve中传入的参数可以在Promise对象的then方法中获取。 22- **reject**:此函数可以将Promise的状态从pending(待定)改为rejected(已拒绝),向reject中传入的参数可以在Promise对象的catch方法中获取。 23 24这些基本概念在处理异步操作中非常重要,开发者需要通过适当的方法来处理异步操作,Promise可以链式调用多个异步操作,使代码清晰整洁,便于维护。JSVM-API提供的方法可以帮助开发者在JSVM模块中处理JavaScript中的异步操作。 25 26## 接口说明 27 28| 接口 | 功能说明 | 29|----------------------------|--------------------------------| 30| OH_JSVM_IsPromise | 查询Promise是否为Promise对象| 31| OH_JSVM_CreatePromise | 创建一个延迟对象和一个JavaScript promise| 32| OH_JSVM_ResolveDeferred | 通过与之关联的延迟对象来解析JavaScript promise| 33| OH_JSVM_RejectDeferred | 通过与之关联的延迟对象来拒绝JavaScript promise| 34| OH_JSVM_PromiseRegisterHandler | 为 Promise 创建兑现或拒绝后的回调 | 35 36## 使用示例 37 38JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅对接口对应C++相关代码进行展示。 39 40### OH_JSVM_IsPromise 41 42判断给定的JSVM_Value是否表示一个Promise对象。 43 44cpp部分代码 45 46```cpp 47// hello.cpp 48#include "napi/native_api.h" 49#include "ark_runtime/jsvm.h" 50#include <hilog/log.h> 51// OH_JSVM_IsPromise的样例方法 52static JSVM_Value IsPromise(JSVM_Env env, JSVM_CallbackInfo info) 53{ 54 size_t argc = 1; 55 JSVM_Value args[1] = {nullptr}; 56 OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr); 57 bool isPromise = false; 58 JSVM_Status status = OH_JSVM_IsPromise(env, args[0], &isPromise); 59 if (status != JSVM_OK) { 60 OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_IsPromise fail"); 61 } else { 62 OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_IsPromise success:%{public}d", isPromise); 63 } 64 JSVM_Value result = nullptr; 65 OH_JSVM_GetBoolean(env, isPromise, &result); 66 return result; 67} 68// IsPromise注册回调 69static JSVM_CallbackStruct param[] = { 70 {.data = nullptr, .callback = IsPromise}, 71}; 72static JSVM_CallbackStruct *method = param; 73// IsPromise方法别名,供JS调用 74static JSVM_PropertyDescriptor descriptor[] = { 75 {"isPromise", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 76}; 77 78// 样例测试js 79const char *srcCallNative = R"JS(isPromise())JS"; 80``` 81<!-- @[oh_jsvm_ispromise](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/JSVMAPI/JsvmUsageGuide/JsvmAboutPromise/ispromise/src/main/cpp/hello.cpp) --> 82 83预期结果: 84``` 85JSVM OH_JSVM_IsPromise success:0 86``` 87 88### OH_JSVM_CreatePromise 89 90OH_JSVM_CreatePromise用于创建一个Promise对象。 91 92### OH_JSVM_ResolveDeferred & OH_JSVM_RejectDeferred 93 94用于对Promise关联的deferred对象进行解析,OH_JSVM_ResolveDeferred将其从挂起状态转换为已兑现状态,OH_JSVM_RejectDeferred将其从挂起状态转换为已拒绝状态。 95 96cpp部分代码 97 98```cpp 99// hello.cpp 100#include "napi/native_api.h" 101#include "ark_runtime/jsvm.h" 102#include <hilog/log.h> 103// OH_JSVM_CreatePromise、OH_JSVM_ResolveDeferred、OH_JSVM_RejectDeferred的样例方法 104static JSVM_Value CreatePromise(JSVM_Env env, JSVM_CallbackInfo info) 105{ 106 JSVM_Deferred defer = nullptr; 107 JSVM_Value promise = nullptr; 108 JSVM_Status status = OH_JSVM_CreatePromise(env, &defer, &promise); 109 bool isPromise = false; 110 JSVM_Value returnIsPromise = nullptr; 111 OH_JSVM_IsPromise(env, promise, &isPromise); 112 if (status != JSVM_OK) { 113 OH_LOG_ERROR(LOG_APP, "JSVM CreatePromise fail"); 114 } else { 115 OH_LOG_INFO(LOG_APP, "JSVM CreatePromise success:%{public}d", isPromise); 116 } 117 // 将布尔值转为可以返回的JSVM_Value 118 OH_JSVM_GetBoolean(env, isPromise, &returnIsPromise); 119 return returnIsPromise; 120} 121 122static JSVM_Value ResolveRejectDeferred(JSVM_Env env, JSVM_CallbackInfo info) 123{ 124 // 获得并解析参数 125 size_t argc = 3; 126 JSVM_Value args[3] = {nullptr}; 127 OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr); 128 // 第一个参数为向resolve传入的信息,第二个参数为向reject传入的信息,第三个参数为Promise的状态 129 bool status = false; 130 OH_JSVM_GetValueBool(env, args[2], &status); 131 // 创建Promise对象 132 JSVM_Deferred deferred = nullptr; 133 JSVM_Value promise = nullptr; 134 JSVM_Status createStatus = OH_JSVM_CreatePromise(env, &deferred, &promise); 135 if (createStatus != JSVM_OK) { 136 OH_JSVM_ThrowError(env, nullptr, "Create promise failed"); 137 return nullptr; 138 } 139 // 根据第三个参数设置resolve或reject 140 if (status) { 141 OH_JSVM_ResolveDeferred(env, deferred, args[0]); 142 OH_LOG_INFO(LOG_APP, "OH_JSVM_ResolveDeferred resolve"); 143 } else { 144 OH_JSVM_RejectDeferred(env, deferred, args[1]); 145 OH_LOG_INFO(LOG_APP, "OH_JSVM_RejectDeferred reject"); 146 } 147 JSVM_Value result = nullptr; 148 OH_JSVM_GetBoolean(env, true, &result); 149 return result; 150} 151// CreatePromise,ResolveRejectDeferred注册回调 152static JSVM_CallbackStruct param[] = { 153 {.data = nullptr, .callback = CreatePromise}, 154 {.data = nullptr, .callback = ResolveRejectDeferred}, 155}; 156static JSVM_CallbackStruct *method = param; 157// CreatePromise,ResolveRejectDeferred方法别名,供JS调用 158static JSVM_PropertyDescriptor descriptor[] = { 159 {"createPromise", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 160 {"resolveRejectDeferred", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, 161}; 162 163// 样例测试js 164const char *srcCallNative = R"JS(createPromise(); 165 resolveRejectDeferred('success', 'fail', true); 166 resolveRejectDeferred('success', 'fail', false);)JS"; 167``` 168<!-- @[oh_jsvm_resolvedeferred_and_rejectdeferred](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/JSVMAPI/JsvmUsageGuide/JsvmAboutPromise/resolvereject/src/main/cpp/hello.cpp) --> 169 170预期结果: 171``` 172JSVM CreatePromise success:1 173OH_JSVM_ResolveDeferred resolve 174OH_JSVM_RejectDeferred reject 175``` 176 177## OH_JSVM_PromiseRegisterHandler 178 179用于设置 Promise 解析或拒绝后的回调,等效于调用原生的 `Promise.then()` 或 `Promise.catch()`。 180 181以下仅对 cpp 部分代码进行展示,其余框架代码如 `TestJSVM` 函数参考 [使用JSVM-API接口进行任务队列相关开发](use-jsvm-execute_tasks.md) OH_JSVM_SetMicrotaskPolicy 段落中的实现。 182 183```cpp 184static int PromiseRegisterHandler(JSVM_VM vm, JSVM_Env env) { 185 const char *defineFunction = R"JS( 186 var x1 = 0; 187 var x2 = 0; 188 function f1(x) { 189 x1 = x; 190 return x + 1; 191 } 192 function f2(x) { 193 x2 = x; 194 return x + 1; 195 } 196 )JS"; 197 198 const char *init = R"JS( 199 x1 = 0; 200 x2 = 0; 201 )JS"; 202 203 JSVM_Script script; 204 JSVM_Value jsSrc; 205 JSVM_Value result; 206 207 // 定义 JS 函数 f1 和 f2 208 CHECK_RET(OH_JSVM_CreateStringUtf8(env, defineFunction, JSVM_AUTO_LENGTH, &jsSrc)); 209 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script)); 210 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 211 212 // 初始化 x1, x2 为 0 213 CHECK_RET(OH_JSVM_CreateStringUtf8(env, init, JSVM_AUTO_LENGTH, &jsSrc)); 214 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script)); 215 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 216 217 // 获取函数 f1 和 f2 218 JSVM_Value global; 219 CHECK_RET(OH_JSVM_GetGlobal(env, &global)); 220 JSVM_Value f1; 221 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "f1", &f1)); 222 JSVM_Value f2; 223 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "f2", &f2)); 224 225 // 创建 Promise 226 JSVM_Value promise; 227 JSVM_Deferred deferred; 228 CHECK_RET(OH_JSVM_CreatePromise(env, &deferred, &promise)); 229 // 为 promise 注册回调函数,并将 then 调用的结果(新的 Promise)赋值给 promise1 230 JSVM_Value promise1; 231 CHECK_RET(OH_JSVM_PromiseRegisterHandler(env, promise, f1, nullptr, &promise1)); 232 // 为 promise1 注册回调函数 233 CHECK_RET(OH_JSVM_PromiseRegisterHandler(env, promise1, f2, nullptr, nullptr)); 234 235 // 获取 promise 解析前 x1 和 x2 的值 236 JSVM_Value x1; 237 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "x1", &x1)); 238 int32_t x1Int = 0; 239 CHECK_RET(OH_JSVM_GetValueInt32(env, x1, &x1Int)); 240 JSVM_Value x2; 241 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "x2", &x2)); 242 int32_t x2Int = 0; 243 CHECK_RET(OH_JSVM_GetValueInt32(env, x2, &x2Int)); 244 OH_LOG_INFO(LOG_APP, "Before promise resolved, x1: %{public}d, x2: %{public}d", x1Int, x2Int); 245 246 // 解析 promise 247 JSVM_Value resolveValue; 248 CHECK_RET(OH_JSVM_CreateInt32(env, 2, &resolveValue)); 249 if (deferred != nullptr) { 250 OH_JSVM_ResolveDeferred(env, deferred, resolveValue); 251 deferred = nullptr; 252 } 253 254 // 获取 promise 解析后 x1 和 x2 的值 255 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "x1", &x1)); 256 CHECK_RET(OH_JSVM_GetValueInt32(env, x1, &x1Int)); 257 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "x2", &x2)); 258 CHECK_RET(OH_JSVM_GetValueInt32(env, x2, &x2Int)); 259 OH_LOG_INFO(LOG_APP, "After promise resolved, x1: %{public}d, x2: %{public}d", x1Int, x2Int); 260 261 return 0; 262} 263 264static void RunDemo(JSVM_VM vm, JSVM_Env env) { 265 if (PromiseRegisterHandler(vm, env) != 0) { 266 OH_LOG_INFO(LOG_APP, "Run PromiseRegisterHandler failed"); 267 } 268} 269``` 270 271预期结果: 272``` 273Before promise resolved, x1: 0, x2: 0 274After promise resolved, x1: 2, x2: 3 275``` 276