[go: up one dir, main page]

Expand description

Async time operators.

This crate provides ergonomic, async time-based operations. It serves as an experimental playground to experiment with how we could potentially add time-based operations to async-std, and subsequently the stdlib.

The goal is to make working with time and other events feel natural. A major source of inspiration for this has been RxJS, which uses events (including time) to trigger operations. This crate takes that principle, inverts the model to make it evaluate lazily, and wraps it in an ergnomic Rust interface.

Examples

Delay a future’s execution by 100ms

use futures_time::prelude::*;
use futures_time::time::Duration;

fn main() {
    async_io::block_on(async {
        let res = async { "meow" }
            .delay(Duration::from_millis(100))
            .await;
        assert_eq!(res, "meow");
    })
}

Error if a future takes longer than 200ms

use futures_time::prelude::*;
use futures_time::time::Duration;

fn main() {
    async_io::block_on(async {
        let res = async { "meow" }
            .delay(Duration::from_millis(100))
            .timeout(Duration::from_millis(200))
            .await;
        assert_eq!(res.unwrap(), "meow");
    })
}

Throttle a stream

This lets two items through in total: one 100ms after the program has started, and one 300ms after the program has started.

use futures_lite::prelude::*;
use futures_time::prelude::*;
use futures_time::time::Duration;
use futures_time::stream;

fn main() {
    async_io::block_on(async {
        let mut counter = 0;
        stream::interval(Duration::from_millis(100))  // Yield an item every 100ms
            .take(4)                                  // Stop after 4 items
            .throttle(Duration::from_millis(300))     // Only let an item through every 300ms
            .for_each(|_| counter += 1)               // Increment a counter for each item
            .await;

        assert_eq!(counter, 2);
    })
}

The Deadline trait

The future returned by task::sleep implements the future::Deadline trait. This represents a future whose deadline can be moved forward into the future.

For example, say we have a deadline of Duration::from_secs(10). By calling Daedline::push_deadline the deadline can be moved into the future relative to now. This functionality is required for methods such as debounce and Stream::timeout, which will regularly want to move their deadlines into the future.

Currently the only type implementing the Deadline trait is task::Sleep, which is created from a Duration. This is in contrast with task::sleep_until, which takes an Instant, and cannot be reset relative to the present time.

Cancellation

You can use future::cancel to create a future::CancelSender and future::CancelReceiver pair. When the “cancel sender” is dropped, all “cancel listeners” will halt execution of the future the next time they are .awaited. This will cause the future to stop executing, and all destructors to be run.

use futures_time::prelude::*;
use futures_time::future::cancel;
use futures_time::time::Duration;

fn main() {
    async_io::block_on(async {
        let (send, recv) = cancel(); // create a new send/receive pair
        let mut counter = 0;
        let value = async { "meow" }
            .delay(Duration::from_millis(100))
            .timeout(recv) // time-out if the sender is dropped.
            .await;

        assert_eq!(value.unwrap(), "meow");
    })
}

Futures

Streams

Modules

Asynchronous values.

The futures-time prelude.

Composable asynchronous iteration.

Types and Traits for working with asynchronous tasks.

Temporal quantification.