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