1# Working with Task Queues Using JSVM-API
2
3## Introduction
4
5JSVM-API provides APIs for processing and dispatching the tasks that are queued up for execution. You can use the APIs to start the running of a task queue in a JSVM and check whether there are micro tasks waiting in the queue. The task queue can be executed cyclically by external events.
6
7## Basic Concepts
8
9- Task queue: a mechanism used to manage the scheduling and execution of asynchronous tasks to ensure that tasks are processed in sequence.
10- Micro task: a small task that needs to be executed as soon as possible. Micro tasks usually have a higher priority.
11
12## Available APIs
13
14| API| Description|
15| -------- | -------- |
16|OH_JSVM_PumpMessageLoop| Starts running a task queue.|
17|OH_JSVM_PerformMicrotaskCheckpoint| Executes micro tasks in a task queue.|
18## Example
19
20If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ code involved in task queue development.
21
22### OH_JSVM_PumpMessageLoop and OH_JSVM_PerformMicrotaskCheckpoint
23
24Use **OH_JSVM_PumpMessageLoop** to start running a task queue.
25
26CPP code:
27
28```cpp
29#include "ark_runtime/jsvm.h"
30#include <cassert>
31#include <string.h>
32#include "hilog/log.h"
33#include <unistd.h>
34#undef  LOG_TAG
35#define LOG_TAG "log"
36#undef  LOG_DOMAIN
37#define LOG_DOMAIN 0x1
38
39// JS code to be executed.
40static const char *STR_TASK = R"JS(
41    // Wasm bytecode (using the add module as an example)
42    // The following is the text format of the Wasm bytecode corresponding to wasmBuffer, which contains only the add function.
43    // (module
44    //   (func $add (param $lhs i32) (param $rhs i32) (result i32)
45    //     local.get $lhs
46    //     local.get $rhs
47    //     i32.add
48    //   )
49    //   (export "add" (func $add))
50    // )
51    var wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
52                                       0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
53                                       0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
54                                       0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b]);
55
56    var p = WebAssembly.instantiate(wasmBytes, {});
57    p.then((result) => {
58        consoleinfo("Called with instance " + result);
59    });
60    p.finally(() => {
61       consoleinfo("Called Finally");
62    });
63)JS";
64
65// Ensure normal printing of the JS code information.
66static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
67    size_t argc = 1;
68    JSVM_Value args[1];
69    char log[256] = "";
70    size_t logLength;
71    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
72
73    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
74    log[255] = 0;
75    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
76    return nullptr;
77}
78
79// Register the consoleinfo callback.
80JSVM_CallbackStruct param[] = {
81    {.data = nullptr, .callback = ConsoleInfo},
82};
83JSVM_PropertyDescriptor descriptor[] = {
84    {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
85};
86
87static int32_t TestJSVM() {
88    JSVM_InitOptions init_options;
89    memset(&init_options, 0, sizeof(init_options));
90    if (g_aa == 0) {
91        OH_JSVM_Init(&init_options);
92        g_aa++;
93    }
94    // Create a JSVM instance and open the VM scope.
95    JSVM_VM vm;
96    JSVM_CreateVMOptions options;
97    memset(&options, 0, sizeof(options));
98    CHECK(OH_JSVM_CreateVM(&options, &vm) == JSVM_OK);
99    JSVM_VMScope vm_scope;
100    CHECK(OH_JSVM_OpenVMScope(vm, &vm_scope) == JSVM_OK);
101
102    JSVM_Env env;
103    CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env) == JSVM_OK);
104    JSVM_EnvScope envScope;
105    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
106    JSVM_HandleScope handlescope;
107    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handlescope));
108    JSVM_Value sourcecodevalue;
109    CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, strlen(STR_TASK), &sourcecodevalue));
110    JSVM_Script script;
111    CHECK_RET(OH_JSVM_CompileScript(env, sourcecodevalue, nullptr, 0, true, nullptr, &script));
112    JSVM_Value result;
113    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
114    bool rst = false;
115    auto start = std::chrono::system_clock::now();
116    while (true) {
117        // If no task is started in the task queue, set rst to false.
118        CHECK_RET(OH_JSVM_PumpMessageLoop(vm, &rst));
119        CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm));
120        // Exit at the scheduled time.
121        auto now = std::chrono::system_clock::now();
122        auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
123        if (cost > 100) {
124            break;
125        }
126    }
127
128    // Close and destroy the environment and the VM.
129    CHECK_RET(OH_JSVM_CloseHandleScope(env, handlescope));
130    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
131    CHECK(OH_JSVM_DestroyEnv(env) == JSVM_OK);
132    CHECK(OH_JSVM_CloseVMScope(vm, vm_scope) == JSVM_OK);
133    CHECK(OH_JSVM_DestroyVM(vm) == JSVM_OK);
134    return 0;
135}
136
137```
138