yew_stdweb/services/
timeout.rs1use super::Task;
5use crate::callback::Callback;
6use cfg_if::cfg_if;
7use cfg_match::cfg_match;
8use std::convert::TryInto;
9use std::fmt;
10use std::time::Duration;
11cfg_if! {
12 if #[cfg(feature = "std_web")] {
13 use stdweb::Value;
14 #[allow(unused_imports)]
15 use stdweb::{_js_impl, js};
16 } else if #[cfg(feature = "web_sys")] {
17 use gloo::timers::callback::Timeout;
18 }
19}
20
21#[must_use = "the timeout will be cleared when the task is dropped"]
23pub struct TimeoutTask(
24 #[cfg(feature = "std_web")] Option<Value>,
25 #[cfg(feature = "web_sys")] Option<Timeout>,
26);
27
28impl fmt::Debug for TimeoutTask {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.write_str("TimeoutTask")
31 }
32}
33
34#[derive(Default, Debug)]
36pub struct TimeoutService {}
37
38impl TimeoutService {
39 pub fn spawn(duration: Duration, callback: Callback<()>) -> TimeoutTask {
45 let callback = move || {
46 callback.emit(());
47 };
48 let ms: u32 = duration
49 .as_millis()
50 .try_into()
51 .expect("duration doesn't fit in u32");
52 let handle = cfg_match! {
53 feature = "std_web" => js! {
54 var callback = @{callback};
55 var action = function() {
56 callback();
57 callback.drop();
58 };
59 var delay = @{ms};
60 return {
61 timeout_id: setTimeout(action, delay),
62 callback: callback,
63 };
64 },
65 feature = "web_sys" => Timeout::new(ms, callback),
66 };
67 TimeoutTask(Some(handle))
68 }
69}
70
71impl Task for TimeoutTask {
72 fn is_active(&self) -> bool {
73 self.0.is_some()
74 }
75}
76
77impl Drop for TimeoutTask {
78 fn drop(&mut self) {
79 #[cfg(feature = "std_web")]
80 {
81 if self.is_active() {
82 let handle = &self.0;
83 js! { @(no_return)
84 var handle = @{handle};
85 clearTimeout(handle.timeout_id);
86 handle.callback.drop();
87 }
88 }
89 }
90 }
91}