I'm working on my first project with rust/wasm_bindgen and I'm using web_sys to make requests to another service.
I have a number of controllers, like the one below, that get called from js with some request parameters and call one function send
that makes the request:
pub async fn get_some_data(&mut self, req_param: String) -> Result<JsValue, JsValue> {
let req_param = String::from(req_param);
let request_endpoint = "some_endpoint";
let request_body = json!({ "req_param": req_param });
let json = self.send(request_endpoint.to_string(), request_body.to_string()).await?;
Ok(json)
}
Here is the send
function:
pub async fn send(&mut self, request_endpoint: String, request_body: String) -> Result<JsValue, JsValue> {
let window = window().ok_or_else(|| JsValue::from_str("Failed to get window object"))?;
// prepare params ...
let mut req = RequestInit::new();
req.method("POST");
req.mode(RequestMode::Cors);
req.body(Some(&JsValue::from_str(&request_body.to_string())));
let request = Request::new_with_str_and_init(&url, &req)?;
request.headers().set("Content-type", "application/json")?;
request.headers().set("Accept", "text/plain")?;
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
let response: Response = resp_value.dyn_into()?;
// check API response
if !response.ok() {
return Err(JsValue::from_str(&format!("HTTP error response: {}",response.status())));
}
// parse API response as JSON and return
let json = JsFuture::from(response.json()?)
.await?;
Ok(json)
}
As I made more controllers, now Im getting the error:
recursive use of an object detected which would lead to unsafe aliasing in rust
Which, I think, happens because the send
function is called concurrently.
In fact, if I delay one of the controllers in js with a setTimeout, the error goes away.
How can I make the send
function handle concurrent requests?
This issue was in one of the codebases I've worked with observed mainly when:
an async
method that had the &mut self
signature was called before/after another method with either &mut self
or &self
was called (concurrent object access).
in TS/JS code a rust wasm function is called inside another rust wasm function, e.g.:
import { f1, f2 } from '../wasm-utils.js'
// where f1 returns a wasm object X that f2 takes as an argument
f2(f1())
In your case the 1) case likely applies, maybe the send
method is called by the JS code at the same time as another piece of code calls this or another method of the object that self
references.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With