Kon*_*hel 5 node.js rust async-await webassembly wasm-bindgen
让我们考虑一个示例导入对象,如下所示:
const importObject = {
exampleAsyncImportFunction: async () => fs.readFile("./someExampleFile.txt", "utf-8") // returns Promise<String>
};
Run Code Online (Sandbox Code Playgroud)
我想在我的 Rust 编写的 WASM 模块中使用它,类似于:
#[wasm_bindgen]
extern "C" {
pub async fn exampleAsyncImportFunction() -> JsValue; // Importing the JS-Function
}
#[wasm_bindgen]
pub async fn exampleExportFunction() -> Result<JsValue, JsValue> {
let theJSPromise = exampleAsyncImportFunction(); // Call the async import function
let promiseResult = theJSPromise.await; // Execute the async import function
// Do sth with the result
OK(JsValue::UNDEFINED)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会导致无法访问的错误。有趣的是,当 JavaScript 函数返回一个字符串时,它确实有效,如下所示:
const importObject = {
exampleAsyncImportFunction: async () => "Some dummy content" // returns Promise<String> as well
};
Run Code Online (Sandbox Code Playgroud)
但当然,异步导入函数应该执行一些实际的异步任务,否则最好使用同步函数。
我尝试做一些研究,发现 'js_sys::Promise' 代表 Rust 中的 JS-Promise,而 'wasm_bindgen_futures::JsFuture' 能够以某种方式将 JS-Promise 转换为 Rust-Future。但我不明白这些类型是否/如何有助于解决问题,以及在这种情况下一般应如何使用它们。
而且,JS-Import-Function 的返回类型(通过声明为“JsValue”)似乎以某种方式实现了“Future”特征。我明白,因此,“等待”结果是可能的。但我很困惑,实际的底层类型是什么(JsFuture、Promise、其他......)。
我希望有人可以帮助我解决实际问题,同时也解释一下所有类型之间的关系(特别是关于 JsValue)。
先感谢您!
我自己找到了解决方案,由于互联网其他地方似乎没有好的信息,我想与有类似问题的任何人分享我的解决方案。
对于导入 JavaScript 函数,重要的是要像函数是同步的一样,尽管它是异步的。原因是,Rust 中的异步函数仅在使用执行器或等待时才会执行。因此,async-JS-Function(其底层是一个返回 Promise 的同步函数)可以同步使用。然后可以显式调用返回的 Promise。
导入部分将如下所示:
#[wasm_bindgen(module = "/some/file.js")]
extern "C" {
pub fn exampleAsyncImportFunction() -> JsValue; // JsValue <==> Promise
// Instead of:
// pub async fn exampleAsyncImportFunction() -> Result<JsValue, JsValue>
}
Run Code Online (Sandbox Code Playgroud)
要使用导入函数,必须将 Promise 作为 JsValue 转换为 js_sys::Promise,然后转换为 wasm_bindgen_futures::JsFuture。之后就可以如期等待了。
原始问题的示例导出函数如下所示:
#[wasm_bindgen]
pub async fn exampleExportFunction() {
// Get a reference to the import function as a 'JsValue'
let promiseAsJsValue = exampleAsyncImportFunction(); // No execution, yet
// Convert 'JsValue' to 'js_sys::Promise', which is a proxy-type for JS-Promises
let promise = js_sys::Promise::from(promiseAsJsValue);
// Convert 'js_sys::Promise' to 'wasm_bindgen_future::JsFuture'
let future = wasm_bindgen_future::JsFuture::from(promise);
// Actually execute the Promise/Future
let result: Result<JsValue, JsValue> = future.await;
// Interpret the result
if let Ok(content) = result {
// do sth with the content
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这种方法,特别是从 JsValue 到 JsFuture 的转换,能够对你们中的一些人有所帮助,因为官方文档没有涵盖该用例,而仅涵盖 js_sys::Promise 的手动实例化(例如 Promise::resolve( &"foo".into()) )或使用 web_sys::window::fetch()。
| 归档时间: |
|
| 查看次数: |
1898 次 |
| 最近记录: |