javascript - Emscripten - 嵌入导出的函数不会从 Javascript 同步运行。使用异步
问题描述
我需要向服务器发出 HTTP 请求,结果是 JSON。结果用于另一个使用 embind 导出的 C++ 函数。
从 js 调用这个导出函数时,它运行很快,无法存储导出函数的值,值为空,稍后 2 秒函数完成但从未分配值。
重现步骤
1.我的测试/假webapi https://jsonplaceholder.typicode.com/
2. 小米JS代码——Instance.js
window.VModule({ noInitialRun: false }).then(module => {
window.VMain = {
Module: module
};
});
window.GetData = async function GetData() {
try {
var url = "https://jsonplaceholder.typicode.com/todos/200"
var options = {
method: "GET",
//mode: "cors",
cache: "default"
};
var response = await fetch(new Request(url), options);
var json = await response.json();
console.log("DATA IN JS: " + json.title);
return json.title;
}
catch (error) {
console.log("DATA IN JS: ERROR_JS");
return "ERROR_JS";
}
}
3. 我的 C++ 代码 - main.cpp - 调用 Instance.js 中定义的“window.GetData”的 EM_JS_GetData 函数 - GetData() 调用 EM_JS_GetData window.GetData() -> EM_JS_GetData -> GetData() -> 来自索引的按钮调用。 html。
#include <iostream>
#include <string>
#include <emscripten.h>
#include <emscripten/bind.h>
typedef std::string String;
EM_JS(const char *, EM_JS_GetData, (), {
return Asyncify.handleSleep(function(wakeUp) {
window.GetData()
.then(data=>{
//Converting JsString to C-String
var lengthBytes = lengthBytesUTF8(data)+1;
var result = _malloc(lengthBytes);
stringToUTF8(data, result, lengthBytes);
wakeUp(result);
})
});
});
String GetData()
{
try
{
const char *cstr = EM_JS_GetData();
String result(cstr);
free(static_cast<void*> (const_cast<char *>(cstr)));
emscripten_console_log((u8"DATA IN C++: " + result).c_str());
return result;
}
catch (...)
{
emscripten_console_log(u8"DATA IN CPP: ERROR_CPP");
return "ERROR_CPP";
}
}
int main(int argc, char ** argv)
{
std::cout<< "All components initialized" << std::endl;
}
EMSCRIPTEN_BINDINGS(my_module)
{
using namespace emscripten;
function("GetData", &GetData);
}
4.我的power shell核心语法中的编译命令。- 编译.ps1
em++.bat `
"main.cpp" `
-o "VModule.js" `
-std=c++17 `
-O2 `
--bind `
-s WASM=1 `
-s SINGLE_FILE=1 `
-s ASYNCIFY=1 `
-s NO_EXIT_RUNTIME=1 `
-s EXTRA_EXPORTED_RUNTIME_METHODS=[`'ccall`',`'cwrap`'] `
-s EXPORT_NAME=`'VModule`' `
-s MODULARIZE=1 `
-s DISABLE_EXCEPTION_CATCHING=0 `
-s ENVIRONMENT=web `
-s ASYNCIFY_IMPORTS=[`'EM_JS_GetData`'] `
-s VERBOSE=0 `
5. 索引.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Validatos - WebAssembly</title>
<link rel="icon" href="Assets/favicon/favicon.ico">
<script type="text/javascript" src="VModule.js"></script>
<script type="module" src="Instance.js"></script>
</head>
<body>
<button onclick="OnBtnClick()">Test</button>
<script type="text/javascript">
function OnBtnClick() {
console.log("BEFORE");
var title = window.VMain.Module.GetData();//RESULT FROM FUNCTION IS NOT ASSIGNED // THIS LINE IS EXECUTED QUICKLY // BUT GetData is now executing.
console.log("DATA IN INDEX.HTML: " + title);//console prints empty string, value was assigned to empty string. GetData continues executing.
console.log("AFTER");
}
</script>
</body>
</html>
当我单击按钮时,我得到以下结果。
All components initialized
(index):17 BEFORE
(index):19 DATA IN INDEX.HTML:
(index):20 AFTER
Instance.js:19 DATA IN JS: ipsam aperiam voluptates qui
VModule.js:9 DATA IN C++: ipsam aperiam voluptates qui
如何同步调用 window.VMain.Module.GetData()?期望的行为
All components initialized
(index):17 BEFORE
Instance.js:19 DATA IN JS: ipsam aperiam voluptates qui
VModule.js:9 DATA IN C++: ipsam aperiam voluptates qui
(index):19 DATA IN INDEX.HTML: ipsam aperiam voluptates qui
(index):20 AFTER
解决方案
推荐阅读
- ruby-on-rails - Phusion 乘客是否重用流程?
- node.js - 如何获取 Firebase 的数据库键和值
- c++ - 在 C++14 中避免字段零初始化
- angular - Web 应用程序 - 浏览器/计算机识别
- java - 我应该得到“无效”作为输出,但我得到“有效”作为输出,不知道为什么输出错误
- json - 如何使用 Moment js 将 Json 对象日期转换为原生反应?
- python - dataframe.to_sql 导入 Teradata(此用户无权在 LABUSERS 上创建) Datalab 表名
- reactjs - 异步/等待反应:对象无效,[对象承诺]
- angular - Angular - 在 3rd 方库中使用 http 拦截器进行身份验证标头 jwt 令牌
- java - 在java中提取花括号之间的字符串