• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用JSVM-API接口进行任务队列相关开发
2
3## 简介
4
5在虚拟机内部启动任务队列的运行,检查是否有微任务在队列中等待,这个任务队列可以由外部事件循环执行。
6
7## 基本概念
8
9- **任务队列**:管理异步任务的调度和执行,确保任务按顺序处理。
10- **微任务**:微任务是一种任务调度机制,主要用于处理那些需要尽快执行的较小任务,它们通常具有较高的优先级。
11
12## 接口说明
13
14| 接口 | 功能说明 |
15| -------- | -------- |
16|OH_JSVM_PumpMessageLoop| 启动任务队列的运行 |
17|OH_JSVM_PerformMicrotaskCheckpoint| 执行任务队列里的微任务 |
18| OH_JSVM_SetMicrotaskPolicy | 设置微任务执行策略 |
19
20## 使用示例
21
22JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅对接口对应C++相关代码进行展示。
23注意:Wasm字节码需要应用拥有JIT权限才能执行,可参考[JSVM 申请JIT权限指导](jsvm-apply-jit-profile.md)申请对应权限。
24### OH_JSVM_PumpMessageLoop && OH_JSVM_PerformMicrotaskCheckpoint
25
26启动任务队列,执行任务。
27
28cpp代码
29
30```cpp
31#include <chrono>
32#include <string.h>
33
34
35// 待执行的js代码
36static const char *STR_TASK = R"JS(
37    // wasm 字节码 (以add 模块为例)
38    // 以下 wasmBuffer 对应的 wasm 字节码文本格式如下所示,只包含了一个函数 add
39    // (module
40    //   (func $add (param $lhs i32) (param $rhs i32) (result i32)
41    //     local.get $lhs
42    //     local.get $rhs
43    //     i32.add
44    //   )
45    //   (export "add" (func $add))
46    // )
47    var wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
48                                       0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
49                                       0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
50                                       0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b]);
51
52    var p = WebAssembly.instantiate(wasmBytes, {});
53    p.then((result) => {
54        consoleinfo("Called with instance " + result);
55    });
56    p.finally(() => {
57       consoleinfo("Called Finally");
58    });
59)JS";
60
61// 保证js代码中的打印信息可以正常输出
62static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
63    size_t argc = 1;
64    JSVM_Value args[1];
65    char log[256] = "";
66    size_t logLength;
67    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
68
69    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
70    log[255] = 0;
71    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
72    return nullptr;
73}
74
75// 注册consoleinfo的方法
76JSVM_CallbackStruct param[] = {
77    {.data = nullptr, .callback = ConsoleInfo},
78};
79JSVM_PropertyDescriptor descriptor[] = {
80    {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
81};
82
83static int32_t TestJSVM() {
84    JSVM_InitOptions init_options;
85    memset(&init_options, 0, sizeof(init_options));
86    if (g_aa == 0) {
87        OH_JSVM_Init(&init_options);
88        g_aa++;
89    }
90    // 创建JavaScript虚拟机实例,打开虚拟机作用域
91    JSVM_VM vm;
92    JSVM_CreateVMOptions options;
93    memset(&options, 0, sizeof(options));
94    CHECK(OH_JSVM_CreateVM(&options, &vm));
95    JSVM_VMScope vm_scope;
96    CHECK(OH_JSVM_OpenVMScope(vm, &vm_scope));
97
98    JSVM_Env env;
99    CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
100    JSVM_EnvScope envScope;
101    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
102    JSVM_HandleScope handlescope;
103    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handlescope));
104    JSVM_Value sourcecodevalue;
105    CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, strlen(STR_TASK), &sourcecodevalue));
106    JSVM_Script script;
107    CHECK_RET(OH_JSVM_CompileScript(env, sourcecodevalue, nullptr, 0, true, nullptr, &script));
108    JSVM_Value result;
109    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
110    bool rst = false;
111    auto start = std::chrono::system_clock::now();
112    while (true) {
113        // 如果任务队列中没有任务启动,则rst设置为false
114        CHECK_RET(OH_JSVM_PumpMessageLoop(vm, &rst));
115        CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm));
116        // 定时退出
117        auto now = std::chrono::system_clock::now();
118        auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
119        if (cost > 100) {
120            break;
121        }
122    }
123
124    // 关闭并销毁环境和虚拟机
125    CHECK_RET(OH_JSVM_CloseHandleScope(env, handlescope));
126    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
127    CHECK(OH_JSVM_DestroyEnv(env));
128    CHECK(OH_JSVM_CloseVMScope(vm, vm_scope));
129    CHECK(OH_JSVM_DestroyVM(vm));
130    return 0;
131}
132
133```
134预期输出结果
135```
136JSVM API TEST: Called with instance [object Object]
137JSVM API TEST: Called Finally
138```
139### OH_JSVM_SetMicrotaskPolicy
140修改微任务执行策略,通过该接口,用户可以将策略设置为 JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT 或 JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO。默认模式下,微任务的执行策略为 JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO。
141
142微任务策略:
143- JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT : 微任务在用户调用 OH_JSVM_PerformMicrotaskCheckpoint 后执行
144- JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO: 微任务在 JS 调用栈为空时自动执行
145
146cpp 部分代码
147
148```
149// OH_JSVM_SetMicrotaskPolicy的样例方法
150static int SetMicrotaskPolicy(JSVM_VM vm, JSVM_Env env) {
151    // 默认或将策略设置为 JSVM_MICROTASK_AUTO 的行为
152    const char *scriptEvalMicrotask = R"JS(
153        evaluateMicrotask = false;
154        Promise.resolve().then(()=>{
155            evaluateMicrotask = true;
156        });
157    )JS";
158    JSVM_Script script;
159    JSVM_Value jsSrc;
160    JSVM_Value result;
161    CHECK_RET(OH_JSVM_CreateStringUtf8(env, scriptEvalMicrotask, JSVM_AUTO_LENGTH, &jsSrc));
162    CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
163    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
164    JSVM_Value global;
165    CHECK_RET(OH_JSVM_GetGlobal(env, &global));
166    JSVM_Value hasEvaluateMicrotask;
167    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
168    bool val;
169    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
170
171    OH_LOG_INFO(LOG_APP, "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : %{public}d", val);
172
173    // 策略设置为 JSVM_MICROTASK_EXPLICIT 的行为
174    CHECK_RET(OH_JSVM_SetMicrotaskPolicy(vm, JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT));
175    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
176    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
177    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
178    OH_LOG_INFO(
179        LOG_APP,
180        "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d",
181        val);
182
183    CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm));
184    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
185    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
186    OH_LOG_INFO(
187        LOG_APP,
188        "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d",
189        val);
190
191    return 0;
192}
193
194static void RunDemo(JSVM_VM vm, JSVM_Env env) {
195    if (SetMicrotaskPolicy(vm, env) != 0) {
196        OH_LOG_INFO(LOG_APP, "Run Microtask Policy failed");
197    }
198}
199
200static int32_t TestJSVM() {
201    JSVM_InitOptions initOptions = {0};
202    JSVM_VM vm;
203    JSVM_Env env = nullptr;
204    JSVM_VMScope vmScope;
205    JSVM_EnvScope envScope;
206    JSVM_HandleScope handleScope;
207    JSVM_Value result;
208    // 初始化JavaScript引擎实例
209    if (g_aa == 0) {
210        g_aa++;
211        CHECK(OH_JSVM_Init(&initOptions));
212    }
213    // 创建JSVM环境
214    CHECK(OH_JSVM_CreateVM(nullptr, &vm));
215    CHECK(OH_JSVM_CreateEnv(vm, 0, nullptr, &env));
216    CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
217    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
218    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
219
220    // 通过script调用测试函数
221    RunDemo(vm, env);
222
223    // 销毁JSVM环境
224    CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
225    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
226    CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
227    CHECK(OH_JSVM_DestroyEnv(env));
228    CHECK(OH_JSVM_DestroyVM(vm));
229    return 0;
230}
231```
232
233预期输出结果
234```
235Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : 1
236Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: 0
237Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: 1
238```
239