mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
add more internal documentation about tasks
This commit is contained in:
parent
48f845985b
commit
b42992bad1
3 changed files with 39 additions and 1 deletions
|
@ -1,3 +1,32 @@
|
|||
//! Dioxus resolves scopes in a specific order to avoid unexpected behavior. All tasks are resolved in the order of height. Scopes that are higher up in the tree are resolved first.
|
||||
//! When a scope that is higher up in the tree is rerendered, it may drop scopes lower in the tree along with their tasks.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use dioxus::prelude::*;
|
||||
//!
|
||||
//! fn app() -> Element {
|
||||
//! let vec = use_signal(|| vec![0; 10]);
|
||||
//! rsx! {
|
||||
//! // If the length of the vec shrinks we need to make sure that the children are dropped along with their tasks the new state of the vec is read
|
||||
//! for idx in 0..vec.len() {
|
||||
//! Child { idx, vec }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[component]
|
||||
//! fn Child(vec: Signal<Vec<usize>>, idx: usize) -> Element {
|
||||
//! use_hook(|| {
|
||||
//! spawn(async {
|
||||
//! // If we let this task run after the child is dropped, it will panic.
|
||||
//! println!("Task {}", vec.read()[idx]);
|
||||
//! });
|
||||
//! });
|
||||
//!
|
||||
//! rsx! {}
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::ScopeId;
|
||||
use crate::Task;
|
||||
use std::borrow::Borrow;
|
||||
|
@ -49,6 +78,7 @@ pub struct DirtyScopes {
|
|||
}
|
||||
|
||||
impl DirtyScopes {
|
||||
/// Queue a task to be polled
|
||||
pub fn queue_task(&mut self, task: Task, order: ScopeOrder) {
|
||||
match self.tasks.get(&order) {
|
||||
Some(scope) => scope.queue_task(task),
|
||||
|
@ -60,22 +90,27 @@ impl DirtyScopes {
|
|||
}
|
||||
}
|
||||
|
||||
/// Queue a scope to be rerendered
|
||||
pub fn queue_scope(&mut self, order: ScopeOrder) {
|
||||
self.scopes.insert(order);
|
||||
}
|
||||
|
||||
/// Check if there are any dirty scopes
|
||||
pub fn has_dirty_scopes(&self) -> bool {
|
||||
!self.scopes.is_empty()
|
||||
}
|
||||
|
||||
/// Take any tasks from the highest scope
|
||||
pub fn pop_task(&mut self) -> Option<DirtyTasks> {
|
||||
self.tasks.pop_first()
|
||||
}
|
||||
|
||||
/// Take the highest scope that needs to be rerendered
|
||||
pub fn pop_scope(&mut self) -> Option<ScopeOrder> {
|
||||
self.scopes.pop_first()
|
||||
}
|
||||
|
||||
/// Take any work from the highest scope. This may include rerunning the scope and/or running tasks
|
||||
pub fn pop_work(&mut self) -> Option<Work> {
|
||||
let dirty_scope = self.scopes.first();
|
||||
let dirty_task = self.tasks.first();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! In dioxus, effects are run using normal async functions after a render. [RenderSignalFuture] is a future that resolves after a render has passed.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
|
|
@ -439,7 +439,7 @@ impl VirtualDom {
|
|||
self.poll_tasks().await;
|
||||
}
|
||||
|
||||
///
|
||||
/// Poll the scheduler for any work
|
||||
async fn poll_tasks(&mut self) {
|
||||
loop {
|
||||
// Process all events - Scopes are marked dirty, etc
|
||||
|
@ -454,6 +454,7 @@ impl VirtualDom {
|
|||
// Make sure we set the runtime since we're running user code
|
||||
let _runtime = RuntimeGuard::new(self.runtime.clone());
|
||||
|
||||
/// There isn't any more work we can do synchronously. Wait for any new work to be ready
|
||||
match self.rx.next().await.expect("channel should never close") {
|
||||
SchedulerMsg::Immediate(id) => self.mark_dirty(id),
|
||||
SchedulerMsg::TaskNotified(id) => {
|
||||
|
|
Loading…
Reference in a new issue