让我们考虑一个例子,导入对象看起来像这样:

const importObject = {
  exampleAsyncImportFunction: async () => fs.readFile("./someExampleFile.txt", "utf-8") // returns Promise<String>
};

我想在我的 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)
}

不幸的是,这会导致无法到达的错误.有趣的是,当JavaScript函数返回一个字符串时,它确实可以工作,如下所示:

const importObject = {
  exampleAsyncImportFunction: async () => "Some dummy content" // returns Promise<String> as well
};

当然,异步导入函数应该执行一些实际的异步任务,否则最好使用同步函数.

I tried to do some research and found 'js_sys::Promise' which represents a JS-Promise in Rust, and 'wasm_bindgen_futures::JsFuture' which enables to somehow convert a JS-Promise to a Rust-Future. But I don't understand, if/how these types may help with the problem and also how they should be used in general in this context.

Also it seems, that the return type of the JS-Import-Function, which is 'JsValue' by declaration, somehow implements the 'Future'-Trait. I understand that due to that, 'awaiting' the result is possible. But I'm confused, what's the actual underlying type (JsFuture, Promise, something else...).

我希望有人能在这方面帮助我,解决实际问题,同时解释一下所有类型之间的关系(尤其是关于JsValue).

提前谢谢!

推荐答案

我自己找到了解决方案,由于互联网上其他地方似乎没有好的信息,我想向任何有类似问题的人分享我的解决方案.

要导入JavaScript函数,尽管函数是异步的,但要像函数是同步的一样操作,这一点很重要.原因是,Rust中的异步函数仅在使用executor或Wait时执行.因此,可以同步使用async JS函数,它是一个返回promise 的同步函数.然后可以显式调用返回的promise .

The import section will look like the following:

#[wasm_bindgen(module = "/some/file.js")]
extern "C" {
  pub fn exampleAsyncImportFunction() -> JsValue; // JsValue <==> Promise
  // Instead of:
  // pub async fn exampleAsyncImportFunction() -> Result<JsValue, JsValue>
}

要使用导入函数,必须将Promise作为JsValue转换为js_sys::Promise,然后再转换为wasm_bindgen_futures::JsFuture.在那之后,可以像预期的那样等待.

The sample export function from the original questions will look like this:

#[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
  }
}

I hope that this approach, specifically the transformation from JsValue to JsFuture, will help some of you, as the official docs don't cover that use case, but only the manual instantiation of a js_sys::Promise (e.g. Promise::resolve(&"foo".into()) ) or using web_sys::window::fetch().

Node.js相关问答推荐

使用Moongose处理node.js中重定向的then()块链

当建议在第二代上运行云功能时,现在是否有新的Firestore AdminClient可供使用?

Express 4.18正文解析

如何使用NodeJS处理来自请求的单个或多个文件?

如何在ejs模板中使用循环显示多个结果?

如何从shell脚本中计算ecmascript模块?

如何使用Next.js/Node/TS正确地上传至S3

错误:0308010C:try 通过 Github 推送部署到 firebase 托管时出现数字

Mongodb聚合传递一个匹配的数组和一个不匹配的数组

使用 mongoose 查找过go 7 天的注册用户总数

node和mongoDB聚合数据时的输入字段函数

如何在 Nest.js 中使用查询参数?

来自 Node-aws 的 Dynamo Local:所有操作都失败无法对不存在的表执行操作

Puppeteer 错误:未下载 Chromium 修订版

如何使用 Mocha 测试正常(非 node 特定)JavaScript 函数?

Node.js + Express:应用程序不会开始监听端口 80

Node.js 中空函数的简写

TypeError:请求路径包含未转义的字符,我该如何解决这个问题

nodeJS - 如何使用 express 创建和读取会话

nodejs:Ajax 与 Socket.IO,优缺点