sauron_core/dom/
timeout.rs1use crate::dom::window;
2use js_sys::Promise;
3use std::rc::Rc;
4use wasm_bindgen::closure::Closure;
5use wasm_bindgen::{JsCast, JsValue};
6use wasm_bindgen_futures::JsFuture;
7
8#[derive(Debug, Clone)]
10pub struct TimeoutCallbackHandle {
11 handle: i32,
12 _closure: Rc<Closure<dyn FnMut()>>,
13}
14
15impl Drop for TimeoutCallbackHandle {
16 fn drop(&mut self) {
17 window().clear_timeout_with_handle(self.handle);
18 }
19}
20
21pub fn request_timeout_callback<F>(f: F, timeout: i32) -> Result<TimeoutCallbackHandle, JsValue>
23where
24 F: FnMut() + 'static,
25{
26 let closure = Closure::once(f);
27 let handle = window().set_timeout_with_callback_and_timeout_and_arguments_0(
28 closure.as_ref().unchecked_ref(),
29 timeout,
30 )?;
31 Ok(TimeoutCallbackHandle {
32 handle,
33 _closure: Rc::new(closure),
34 })
35}
36
37pub(crate) async fn async_delay(timeout: i32) -> Result<TimeoutCallbackHandle, JsValue> {
39 let mut result = Err(JsValue::NULL);
40 let promise = Promise::new(&mut |resolve, _reject| {
41 let handle = request_timeout_callback(
42 move || {
43 resolve
44 .call0(&JsValue::NULL)
45 .expect("must be able to call resolve");
46 },
47 timeout,
48 );
49 result = handle;
50 });
51 JsFuture::from(promise).await.expect("must not error");
52 result
53}
54
55pub async fn delay(timeout: i32) {
57 async_delay(timeout).await.expect("must not error");
58}