You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Yew中使用异步函数作为yew::callback::Callback?

在Yew中使用异步函数作为Callback的解决方案

问题场景

我在Yew中为onsubmit事件注册了如下Callback:

use gloo::net::http::Request;
use yew::prelude::*;

let on_submit = Callback::from(async move |ev: FocusEvent| {
    ev.prevent_default();

    let res = Request::post("https://formsubmit.co/srineshnisala@gmail.com")
        .send()
        .await
        .unwrap();

    assert_eq!(res.status(), 200);
});

但使用async时触发了以下编译错误:

--> src/pages/contact/contact.rs:26:36
   |
26 |       let on_submit = Callback::from(async move |ev: FocusEvent| {
   |  _____________________--------------_^
   | |                     |
   | |                     required by a bound introduced by this call
27 | |         ev.prevent_default();
28 | |
29 | |         let res = Request::post("https://formsubmit.co/srineshnisala@gmail.com")
...  |
34 | |         assert_eq!(res.status(), 200);
35 | |     });
   | |_____^ expected `()`, found opaque type
   |
  ::: /home/s1n7ax/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:72:43
   |
72 |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
   |                                             ------------------------------- the found opaque type
   |
   = note: expected unit type `()`
            found opaque type `impl Future<Output = ()>`
   = note: required for `yew::Callback<yew::FocusEvent>` to implement `From<[closure@src/pages/contact/contact.rs:26:36: 26:63]>`

使用的环境版本:

  • Rust版本:rustc 1.66.0-nightly (01af5040f 2022-10-04)
  • 依赖包版本:
yew = "0.19.3"
yew-router = "0.16.0"
gloo = "0.7.0" # console log and stuff
hyper = "0.14.19" # http requests

解决方案

Yew的Callback要求传入的闭包返回值为(),但异步闭包会返回impl Future<Output = ()>类型,这与Callback的类型要求不匹配,从而导致编译错误。要解决这个问题,需要将异步逻辑包裹在wasm_bindgen_futures::spawn_local函数中,让异步任务在浏览器的事件循环中执行,外层闭包则返回()以符合Callback的要求。

修改后的代码

use gloo::net::http::Request;
use wasm_bindgen_futures::spawn_local;
use yew::prelude::*;

let on_submit = Callback::from(move |ev: FocusEvent| {
    ev.prevent_default();
    
    // 将异步任务提交到本地事件队列执行
    spawn_local(async move {
        let res = Request::post("https://formsubmit.co/srineshnisala@gmail.com")
            .send()
            .await
            .unwrap();

        assert_eq!(res.status(), 200);
    });
});

补充说明

  • 需要在Cargo.toml中添加wasm-bindgen-futures依赖:
wasm-bindgen-futures = "0.4"
  • spawn_local的作用是将异步任务绑定到WebAssembly的本地事件循环,确保异步代码能够被正确调度执行,同时不会阻塞主线程。

内容的提问来源于stack exchange,提问作者s1n7ax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:31:44