I'm working on a function which makes a request to an API, pulls the data, and parses it before returning the data as a Vector of a particular type. Because this is part of a Yew project, tokio and other packages are incompatible. I'm using the wasm-bindgen-futures
crate and the spawn_local
function from within.
The following is a (skelotonized) failed attempt to complete the relatively simple task. The problem is that the compiler displays is use of moved value: 'games_tonight'
. I'm struggling to understand the lower level operations taking place here, and thus the solution to this problem.
pub fn get_sched() -> Vec<MyObj> {
let mut games_tonight = Vec::new();
wasm_bindgen_futures::spawn_local(async move {
let response: myStruct = Request::get(" http://...url...").send().await.unwrap().json().await.unwrap();
let raw_json = &response.dates[0].games;
for g in raw_json.to_owned() {
games_tonight.push(MyObj {
// LOGIC HERE TO CREATE INSTANCES OF MyObj
});
}
});
games_tonight
}
The problem is that move
blocks move all variables referenced in them into their body.
You can just convert the function into an async one:
#[derive(Clone)]
pub struct MyObj {}
pub async fn get_sched() -> Vec<MyObj> {
let response: myStruct = Request::get("http://...url...")
.send()
.await
.unwrap()
.json()
.await
.unwrap();
let mut games_tonight = Vec::new();
let raw_json = &response.dates[0].games;
for g in raw_json.to_owned() {
games_tonight.push(MyObj {
// LOGIC HERE TO CREATE INSTANCES OF MyObj
});
}
}
and use spawn_local
from within the component that also has access to it's state:
use yew::prelude::*;
#[function_component(ComponentName)]
fn component() -> Html {
let games = use_state(|| Vec::new());
wasm_bindgen_futures::spawn_local({
let games = games.clone();
async move {
games.set(get_sched().await);
}
});
html! {<>
// use games
</>}
}