• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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