Struct ArcAction

pub struct ArcAction<I, O> {
    in_flight: ArcRwSignal<usize>,
    input: ArcRwSignal<SendOption<I>>,
    value: ArcRwSignal<SendOption<O>>,
    version: ArcRwSignal<usize>,
    dispatched: ArcStoredValue<usize>,
    action_fn: Arc<dyn Fn(&I) -> Pin<Box<dyn Future<Output = O> + Send>> + Send + Sync>,
}
Expand description

An action runs some asynchronous code when you dispatch a new value to it, and gives you reactive access to the result.

Actions are intended for mutating or updating data, not for loading data. If you find yourself creating an action and immediately dispatching a value to it, this is probably the wrong primitive.

The arena-allocated, Copy version of an ArcAction is an Action.

async fn send_new_todo_to_api(task: String) -> usize {
    // do something...
    // return a task id
    42
}
let save_data = ArcAction::new(|task: &String| {
  // `task` is given as `&String` because its value is available in `input`
  send_new_todo_to_api(task.clone())
});

// the argument currently running
let input = save_data.input();
// the most recent returned result
let result_of_call = save_data.value();
// whether the call is pending
let pending = save_data.pending();
// how many times the action has run
// useful for reactively updating something else in response to a `dispatch` and response
let version = save_data.version();

// before we do anything
assert_eq!(input.get(), None); // no argument yet
assert_eq!(pending.get(), false); // isn't pending a response
assert_eq!(result_of_call.get(), None); // there's no "last value"
assert_eq!(version.get(), 0);

// dispatch the action
save_data.dispatch("My todo".to_string());

// when we're making the call
assert_eq!(input.get(), Some("My todo".to_string()));
assert_eq!(pending.get(), true); // is pending
assert_eq!(result_of_call.get(), None); // has not yet gotten a response


// after call has resolved
assert_eq!(input.get(), None); // input clears out after resolved
assert_eq!(pending.get(), false); // no longer pending
assert_eq!(result_of_call.get(), Some(42));
assert_eq!(version.get(), 1);

The input to the async function should always be a single value, but it can be of any type. The argument is always passed by reference to the function, because it is stored in Action::input as well.

// if there's a single argument, just use that
let action1 = ArcAction::new(|input: &String| {
    let input = input.clone();
    async move { todo!() }
});

// if there are no arguments, use the unit type `()`
let action2 = ArcAction::new(|input: &()| async { todo!() });

// if there are multiple arguments, use a tuple
let action3 = ArcAction::new(|input: &(usize, String)| async { todo!() });

Fields§

§in_flight: ArcRwSignal<usize>§input: ArcRwSignal<SendOption<I>>§value: ArcRwSignal<SendOption<O>>§version: ArcRwSignal<usize>§dispatched: ArcStoredValue<usize>§action_fn: Arc<dyn Fn(&I) -> Pin<Box<dyn Future<Output = O> + Send>> + Send + Sync>

Implementations§

§

impl<I, O> ArcAction<I, O>
where I: 'static, O: 'static,

pub fn new<F, Fu>(action_fn: F) -> ArcAction<I, O>
where F: Fn(&I) -> Fu + Send + Sync + 'static, Fu: Future<Output = O> + Send + 'static, I: Send + Sync, O: Send + Sync,

Creates a new action. This is lazy: it does not run the action function until some value is dispatched.

The constructor takes a function which will create a new Future from some input data. When the action is dispatched, this action_fn will run, and the Future it returns will be spawned.

The action_fn must be Send + Sync so that the ArcAction is Send + Sync. The Future must be Send so that it can be moved across threads by the async executor as needed.

let act = ArcAction::new(|n: &u8| {
    let n = n.to_owned();
    async move { n * 2 }
});

act.dispatch(3);
assert_eq!(act.input().get(), Some(3));

// Remember that async functions already return a future if they are
// not `await`ed. You can save keystrokes by leaving out the `async move`

let act2 = Action::new(|n: &String| yell(n.to_owned()));
act2.dispatch(String::from("i'm in a doctest"));

// after it resolves
assert_eq!(act2.value().get(), Some("I'M IN A DOCTEST".to_string()));

async fn yell(n: String) -> String {
    n.to_uppercase()
}

pub fn new_with_value<F, Fu>(value: Option<O>, action_fn: F) -> ArcAction<I, O>
where F: Fn(&I) -> Fu + Send + Sync + 'static, Fu: Future<Output = O> + Send + 'static, I: Send + Sync, O: Send + Sync,

Creates a new action, initializing it with the given value.

This is lazy: it does not run the action function until some value is dispatched.

The constructor takes a function which will create a new Future from some input data. When the action is dispatched, this action_fn will run, and the Future it returns will be spawned.

The action_fn must be Send + Sync so that the ArcAction is Send + Sync. The Future must be Send so that it can be moved across threads by the async executor as needed.

pub fn clear(&self)

Clears the value of the action, setting its current value to None.

This has no other effect: i.e., it will not cancel in-flight actions, set the input, etc.

§

impl<I, O> ArcAction<I, O>
where I: Send + Sync + 'static, O: Send + Sync + 'static,

pub fn dispatch(&self, input: I) -> ActionAbortHandle

Calls the async function with a reference to the input type as its argument.

§

impl<I, O> ArcAction<I, O>
where I: 'static, O: 'static,

pub fn dispatch_local(&self, input: I) -> ActionAbortHandle

Calls the async function with a reference to the input type as its argument, ensuring that it is spawned on the current thread.

§

impl<I, O> ArcAction<I, O>
where I: 'static, O: 'static,

pub fn new_unsync<F, Fu>(action_fn: F) -> ArcAction<I, O>
where F: Fn(&I) -> Fu + 'static, Fu: Future<Output = O> + 'static,

Creates a new action, which will only be run on the thread in which it is created.

In all other ways, this is identical to ArcAction::new.

pub fn new_unsync_with_value<F, Fu>( value: Option<O>, action_fn: F, ) -> ArcAction<I, O>
where F: Fn(&I) -> Fu + 'static, Fu: Future<Output = O> + 'static,

Creates a new action that will only run on the current thread, initializing it with the given value.

In all other ways, this is identical to ArcAction::new_with_value.

§

impl<I, O> ArcAction<I, O>
where I: 'static, O: 'static,

pub fn version(&self) -> ArcRwSignal<usize>

The number of times the action has successfully completed.

let act = ArcAction::new(|n: &u8| {
    let n = n.to_owned();
    async move { n * 2 }
});

let version = act.version();
act.dispatch(3);
assert_eq!(version.get(), 0);

// after it resolves
assert_eq!(version.get(), 1);

pub fn input(&self) -> ArcMappedSignal<Option<I>>

The current argument that was dispatched to the async function. This value will be Some while we are waiting for it to resolve, and None after it has resolved.

let act = ArcAction::new(|n: &u8| {
    let n = n.to_owned();
    async move { n * 2 }
});

let input = act.input();
assert_eq!(input.get(), None);
act.dispatch(3);
assert_eq!(input.get(), Some(3));

// after it resolves
assert_eq!(input.get(), None);

pub fn value(&self) -> ArcMappedSignal<Option<O>>

The most recent return value of the async function. This will be None before the action has ever run successfully, and subsequently will always be Some(_), holding the old value until a new value has been received.

let act = ArcAction::new(|n: &u8| {
    let n = n.to_owned();
    async move { n * 2 }
});

let value = act.value();
assert_eq!(value.get(), None);
act.dispatch(3);
assert_eq!(value.get(), None);

// after it resolves
assert_eq!(value.get(), Some(6));
// dispatch another value, and it still holds the old value
act.dispatch(3);
assert_eq!(value.get(), Some(6));

pub fn pending(&self) -> ArcMemo<bool>

Whether the action has been dispatched and is currently waiting to resolve.

let act = ArcAction::new(|n: &u8| {
    let n = n.to_owned();
    async move { n * 2 }
});

let pending = act.pending();
assert_eq!(pending.get(), false);
act.dispatch(3);
assert_eq!(pending.get(), true);

// after it resolves
assert_eq!(pending.get(), false);

Trait Implementations§

§

impl<I, O> Clone for ArcAction<I, O>

§

fn clone(&self) -> ArcAction<I, O>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl<I, O> DefinedAt for ArcAction<I, O>
where I: 'static, O: 'static,

§

fn defined_at(&self) -> Option<&'static Location<'static>>

Returns the location at which the signal was defined. This is usually simply None in release mode.

Auto Trait Implementations§

§

impl<I, O> Freeze for ArcAction<I, O>

§

impl<I, O> !RefUnwindSafe for ArcAction<I, O>

§

impl<I, O> Send for ArcAction<I, O>

§

impl<I, O> Sync for ArcAction<I, O>

§

impl<I, O> Unpin for ArcAction<I, O>

§

impl<I, O> !UnwindSafe for ArcAction<I, O>

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> ArchivePointee for T

§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
§

impl<F, W, T, D> Deserialize<With<T, W>, D> for F
where W: DeserializeWith<F, T, D>, D: Fallible + ?Sized, F: ?Sized,

§

fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>

Deserializes using the given deserializer
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSend for T
where T: Any + Send,

§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
§

impl<T> FromRef<T> for T
where T: Clone,

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<E, T, Request, Encoding> FromReq<Patch<Encoding>, Request, E> for T
where Request: Req<E> + Send + 'static, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_req(req: Request) -> Result<T, E>

Attempts to deserialize the arguments from a request.
§

impl<E, T, Request, Encoding> FromReq<Post<Encoding>, Request, E> for T
where Request: Req<E> + Send + 'static, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_req(req: Request) -> Result<T, E>

Attempts to deserialize the arguments from a request.
§

impl<E, T, Request, Encoding> FromReq<Put<Encoding>, Request, E> for T
where Request: Req<E> + Send + 'static, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_req(req: Request) -> Result<T, E>

Attempts to deserialize the arguments from a request.
§

impl<E, Encoding, Response, T> FromRes<Patch<Encoding>, Response, E> for T
where Response: ClientRes<E> + Send, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_res(res: Response) -> Result<T, E>

Attempts to deserialize the outputs from a response.
§

impl<E, Encoding, Response, T> FromRes<Post<Encoding>, Response, E> for T
where Response: ClientRes<E> + Send, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_res(res: Response) -> Result<T, E>

Attempts to deserialize the outputs from a response.
§

impl<E, Encoding, Response, T> FromRes<Put<Encoding>, Response, E> for T
where Response: ClientRes<E> + Send, Encoding: Decodes<T>, E: FromServerFnError,

§

async fn from_res(res: Response) -> Result<T, E>

Attempts to deserialize the outputs from a response.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<E, T, Encoding, Request> IntoReq<Patch<Encoding>, Request, E> for T
where Request: ClientReq<E>, Encoding: Encodes<T>, E: FromServerFnError,

§

fn into_req(self, path: &str, accepts: &str) -> Result<Request, E>

Attempts to serialize the arguments into an HTTP request.
§

impl<E, T, Encoding, Request> IntoReq<Post<Encoding>, Request, E> for T
where Request: ClientReq<E>, Encoding: Encodes<T>, E: FromServerFnError,

§

fn into_req(self, path: &str, accepts: &str) -> Result<Request, E>

Attempts to serialize the arguments into an HTTP request.
§

impl<E, T, Encoding, Request> IntoReq<Put<Encoding>, Request, E> for T
where Request: ClientReq<E>, Encoding: Encodes<T>, E: FromServerFnError,

§

fn into_req(self, path: &str, accepts: &str) -> Result<Request, E>

Attempts to serialize the arguments into an HTTP request.
§

impl<E, Response, Encoding, T> IntoRes<Patch<Encoding>, Response, E> for T
where Response: TryRes<E>, Encoding: Encodes<T>, E: FromServerFnError + Send, T: Send,

§

async fn into_res(self) -> Result<Response, E>

Attempts to serialize the output into an HTTP response.
§

impl<E, Response, Encoding, T> IntoRes<Post<Encoding>, Response, E> for T
where Response: TryRes<E>, Encoding: Encodes<T>, E: FromServerFnError + Send, T: Send,

§

async fn into_res(self) -> Result<Response, E>

Attempts to serialize the output into an HTTP response.
§

impl<E, Response, Encoding, T> IntoRes<Put<Encoding>, Response, E> for T
where Response: TryRes<E>, Encoding: Encodes<T>, E: FromServerFnError + Send, T: Send,

§

async fn into_res(self) -> Result<Response, E>

Attempts to serialize the output into an HTTP response.
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Metadata = ()

The type for metadata in pointers and references to Self.
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> SerializableKey for T

§

fn ser_key(&self) -> String

Serializes the key to a unique string. Read more
§

impl<T> StorageAccess<T> for T

§

fn as_borrowed(&self) -> &T

Borrows the value.
§

fn into_taken(self) -> T

Takes the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> Fruit for T
where T: Send + Downcast,