Function iced::subscription::channel

source ·
pub fn channel<I, Fut, Message>(
    id: I,
    size: usize,
    f: impl FnOnce(Sender<Message>) -> Fut + MaybeSend + 'static
) -> Subscription<Message>where
    I: Hash + 'static,
    Fut: Future<Output = Infallible> + MaybeSend + 'static,
    Message: 'static + MaybeSend,
Expand description

Creates a Subscription that publishes the events sent from a Future to an [mpsc::Sender] with the given bounds.

Creating an asynchronous worker with bidirectional communication

You can leverage this helper to create a Subscription that spawns an asynchronous worker in the background and establish a channel of communication with an iced application.

You can achieve this by creating an mpsc channel inside the closure and returning the Sender as a Message for the Application:

use iced_futures::subscription::{self, Subscription};
use iced_futures::futures::channel::mpsc;
use iced_futures::futures::sink::SinkExt;

pub enum Event {
    Ready(mpsc::Sender<Input>),
    WorkFinished,
    // ...
}

enum Input {
    DoSomeWork,
    // ...
}

enum State {
    Starting,
    Ready(mpsc::Receiver<Input>),
}

fn some_worker() -> Subscription<Event> {
    struct SomeWorker;

    subscription::channel(std::any::TypeId::of::<SomeWorker>(), 100, |mut output| async move {
        let mut state = State::Starting;

        loop {
            match &mut state {
                State::Starting => {
                    // Create channel
                    let (sender, receiver) = mpsc::channel(100);

                    // Send the sender back to the application
                    output.send(Event::Ready(sender)).await;

                    // We are ready to receive messages
                    state = State::Ready(receiver);
                }
                State::Ready(receiver) => {
                    use iced_futures::futures::StreamExt;

                    // Read next input sent from `Application`
                    let input = receiver.select_next_some().await;

                    match input {
                        Input::DoSomeWork => {
                            // Do some async work...

                            // Finally, we can optionally produce a message to tell the
                            // `Application` the work is done
                            output.send(Event::WorkFinished).await;
                        }
                    }
                }
            }
        }
    })
}

Check out the websocket example, which showcases this pattern to maintain a WebSocket connection open.