usefuture.rs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #![allow(missing_docs)]
  2. use dioxus_core::{ScopeState, TaskId};
  3. use std::{
  4. any::Any,
  5. cell::{Cell, RefCell},
  6. future::{Future, IntoFuture},
  7. rc::Rc,
  8. sync::Arc,
  9. };
  10. /// A future that resolves to a value.
  11. ///
  12. /// This runs the future only once - though the future may be regenerated
  13. /// through the [`UseFuture::restart`] method.
  14. ///
  15. /// This is commonly used for components that cannot be rendered until some
  16. /// asynchronous operation has completed.
  17. ///
  18. /// Whenever the hooks dependencies change, the future will be re-evaluated.
  19. /// If a future is pending when the dependencies change, the previous future
  20. /// will be allowed to continue
  21. ///
  22. /// - dependencies: a tuple of references to values that are PartialEq + Clone
  23. pub fn use_future<T, F, D>(
  24. cx: &ScopeState,
  25. dependencies: D,
  26. future: impl FnOnce(D::Out) -> F,
  27. ) -> &UseFuture<T>
  28. where
  29. T: 'static,
  30. F: Future<Output = T> + 'static,
  31. D: UseFutureDep,
  32. {
  33. let state = cx.use_hook(move || UseFuture {
  34. update: cx.schedule_update(),
  35. needs_regen: Cell::new(true),
  36. values: Default::default(),
  37. task: Cell::new(None),
  38. dependencies: Vec::new(),
  39. waker: Default::default(),
  40. });
  41. *state.waker.borrow_mut() = None;
  42. if dependencies.clone().apply(&mut state.dependencies) || state.needs_regen.get() {
  43. // We don't need regen anymore
  44. state.needs_regen.set(false);
  45. // Create the new future
  46. let fut = future(dependencies.out());
  47. // Clone in our cells
  48. let values = state.values.clone();
  49. let schedule_update = state.update.clone();
  50. let waker = state.waker.clone();
  51. // Cancel the current future
  52. if let Some(current) = state.task.take() {
  53. cx.remove_future(current);
  54. }
  55. state.task.set(Some(cx.push_future(async move {
  56. let res = fut.await;
  57. values.borrow_mut().push(Box::leak(Box::new(res)));
  58. // if there's a waker, we dont re-render the component. Instead we just progress that future
  59. match waker.borrow().as_ref() {
  60. Some(waker) => waker.wake_by_ref(),
  61. None => schedule_update(),
  62. }
  63. })));
  64. }
  65. state
  66. }
  67. pub enum FutureState<'a, T> {
  68. Pending,
  69. Complete(&'a T),
  70. Regenerating(&'a T), // the old value
  71. }
  72. pub struct UseFuture<T> {
  73. update: Arc<dyn Fn()>,
  74. needs_regen: Cell<bool>,
  75. task: Cell<Option<TaskId>>,
  76. dependencies: Vec<Box<dyn Any>>,
  77. waker: Rc<RefCell<Option<std::task::Waker>>>,
  78. values: Rc<RefCell<Vec<*mut T>>>,
  79. }
  80. pub enum UseFutureState<'a, T> {
  81. Pending,
  82. Complete(&'a T),
  83. Reloading(&'a T),
  84. }
  85. impl<T> UseFuture<T> {
  86. /// Restart the future with new dependencies.
  87. ///
  88. /// Will not cancel the previous future, but will ignore any values that it
  89. /// generates.
  90. pub fn restart(&self) {
  91. self.needs_regen.set(true);
  92. (self.update)();
  93. }
  94. /// Forcefully cancel a future
  95. pub fn cancel(&self, cx: &ScopeState) {
  96. if let Some(task) = self.task.take() {
  97. cx.remove_future(task);
  98. }
  99. }
  100. // clears the value in the future slot without starting the future over
  101. pub fn clear(&self) -> Option<T> {
  102. todo!()
  103. // (self.update)();
  104. // self.slot.replace(None)
  105. }
  106. // Manually set the value in the future slot without starting the future over
  107. pub fn set(&self, _new_value: T) {
  108. // self.slot.set(Some(new_value));
  109. // self.needs_regen.set(true);
  110. // (self.update)();
  111. todo!()
  112. }
  113. /// Return any value, even old values if the future has not yet resolved.
  114. ///
  115. /// If the future has never completed, the returned value will be `None`.
  116. pub fn value(&self) -> Option<&T> {
  117. self.values
  118. .borrow_mut()
  119. .last()
  120. .cloned()
  121. .map(|x| unsafe { &*x })
  122. }
  123. /// Get the ID of the future in Dioxus' internal scheduler
  124. pub fn task(&self) -> Option<TaskId> {
  125. self.task.get()
  126. }
  127. /// Get the current state of the future.
  128. pub fn state(&self) -> UseFutureState<T> {
  129. match (&self.task.get(), &self.value()) {
  130. // If we have a task and an existing value, we're reloading
  131. (Some(_), Some(val)) => UseFutureState::Reloading(val),
  132. // no task, but value - we're done
  133. (None, Some(val)) => UseFutureState::Complete(val),
  134. // no task, no value - something's wrong? return pending
  135. (None, None) => UseFutureState::Pending,
  136. // Task, no value - we're still pending
  137. (Some(_), None) => UseFutureState::Pending,
  138. }
  139. }
  140. }
  141. impl<'a, T> IntoFuture for &'a UseFuture<T> {
  142. type Output = &'a T;
  143. type IntoFuture = UseFutureAwait<'a, T>;
  144. fn into_future(self) -> Self::IntoFuture {
  145. UseFutureAwait { hook: self }
  146. }
  147. }
  148. pub struct UseFutureAwait<'a, T> {
  149. hook: &'a UseFuture<T>,
  150. }
  151. impl<'a, T> Future for UseFutureAwait<'a, T> {
  152. type Output = &'a T;
  153. fn poll(
  154. self: std::pin::Pin<&mut Self>,
  155. cx: &mut std::task::Context<'_>,
  156. ) -> std::task::Poll<Self::Output> {
  157. match self.hook.values.borrow_mut().last().cloned() {
  158. Some(value) => std::task::Poll::Ready(unsafe { &*value }),
  159. None => {
  160. self.hook.waker.replace(Some(cx.waker().clone()));
  161. std::task::Poll::Pending
  162. }
  163. }
  164. }
  165. }
  166. pub trait UseFutureDep: Sized + Clone {
  167. type Out;
  168. fn out(&self) -> Self::Out;
  169. fn apply(self, state: &mut Vec<Box<dyn Any>>) -> bool;
  170. }
  171. impl UseFutureDep for () {
  172. type Out = ();
  173. fn out(&self) -> Self::Out {}
  174. fn apply(self, _state: &mut Vec<Box<dyn Any>>) -> bool {
  175. false
  176. }
  177. }
  178. pub trait Dep: 'static + PartialEq + Clone {}
  179. impl<T> Dep for T where T: 'static + PartialEq + Clone {}
  180. impl<A: Dep> UseFutureDep for &A {
  181. type Out = A;
  182. fn out(&self) -> Self::Out {
  183. (*self).clone()
  184. }
  185. fn apply(self, state: &mut Vec<Box<dyn Any>>) -> bool {
  186. match state.get_mut(0).and_then(|f| f.downcast_mut::<A>()) {
  187. Some(val) => {
  188. if *val != *self {
  189. *val = self.clone();
  190. return true;
  191. }
  192. }
  193. None => {
  194. state.push(Box::new(self.clone()));
  195. return true;
  196. }
  197. }
  198. false
  199. }
  200. }
  201. macro_rules! impl_dep {
  202. (
  203. $($el:ident=$name:ident,)*
  204. ) => {
  205. impl< $($el),* > UseFutureDep for ($(&$el,)*)
  206. where
  207. $(
  208. $el: Dep
  209. ),*
  210. {
  211. type Out = ($($el,)*);
  212. fn out(&self) -> Self::Out {
  213. let ($($name,)*) = self;
  214. ($((*$name).clone(),)*)
  215. }
  216. #[allow(unused)]
  217. fn apply(self, state: &mut Vec<Box<dyn Any>>) -> bool {
  218. let ($($name,)*) = self;
  219. let mut idx = 0;
  220. let mut needs_regen = false;
  221. $(
  222. match state.get_mut(idx).map(|f| f.downcast_mut::<$el>()).flatten() {
  223. Some(val) => {
  224. if *val != *$name {
  225. *val = $name.clone();
  226. needs_regen = true;
  227. }
  228. }
  229. None => {
  230. state.push(Box::new($name.clone()));
  231. needs_regen = true;
  232. }
  233. }
  234. idx += 1;
  235. )*
  236. needs_regen
  237. }
  238. }
  239. };
  240. }
  241. impl_dep!(A = a,);
  242. impl_dep!(A = a, B = b,);
  243. impl_dep!(A = a, B = b, C = c,);
  244. impl_dep!(A = a, B = b, C = c, D = d,);
  245. impl_dep!(A = a, B = b, C = c, D = d, E = e,);
  246. impl_dep!(A = a, B = b, C = c, D = d, E = e, F = f,);
  247. impl_dep!(A = a, B = b, C = c, D = d, E = e, F = f, G = g,);
  248. impl_dep!(A = a, B = b, C = c, D = d, E = e, F = f, G = g, H = h,);
  249. /// A helper macro that merges uses the closure syntax to elaborate the dependency array
  250. #[macro_export]
  251. macro_rules! use_future {
  252. ($cx:ident, || $($rest:tt)*) => { use_future( $cx, (), |_| $($rest)* ) };
  253. ($cx:ident, | $($args:tt),* | $($rest:tt)*) => {
  254. use_future(
  255. $cx,
  256. ($($args),*),
  257. |($($args),*)| $($rest)*
  258. )
  259. };
  260. }
  261. #[cfg(test)]
  262. mod tests {
  263. use super::*;
  264. #[allow(unused)]
  265. #[test]
  266. fn test_use_future() {
  267. use dioxus_core::prelude::*;
  268. struct MyProps {
  269. a: String,
  270. b: i32,
  271. c: i32,
  272. d: i32,
  273. e: i32,
  274. }
  275. async fn app(cx: Scope<'_, MyProps>) -> Element {
  276. // should only ever run once
  277. let fut = use_future(cx, (), |_| async move {});
  278. // runs when a is changed
  279. let fut = use_future(cx, (&cx.props.a,), |(a,)| async move {});
  280. // runs when a or b is changed
  281. let fut = use_future(cx, (&cx.props.a, &cx.props.b), |(a, b)| async move { 123 });
  282. let a = use_future!(cx, || async move {
  283. // do the thing!
  284. });
  285. let b = &123;
  286. let c = &123;
  287. let a = use_future!(cx, |b, c| async move {
  288. let a = b + c;
  289. let blah = "asd";
  290. });
  291. let g2 = a.await;
  292. let g = fut.await;
  293. todo!()
  294. }
  295. }
  296. }