Skip to content

How to pass channel into Closure? #1269

Closed
@dakom

Description

@dakom

Picking up from #1126

Consider the following:

use futures::{Future, Async, Poll};
use futures::sync::oneshot::{Sender, Receiver, channel};
use futures::task::current;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::*;

struct AsyncCounter {
    value: f64,
    target: f64,
    state: CounterState,
}

enum CounterState {
    Init,
    Counting { err_receiver: Receiver<JsValue> },
    Error (JsValue)
}
impl Future for AsyncCounter {
    type Item = JsValue;
    type Error = JsValue;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match &self.state {
            CounterState::Init => {
                //Setup callback for updates
                let (err_sender, err_receiver):(Sender<JsValue>, Receiver<JsValue>) = channel();
                let task = current();

                let closure = Closure::wrap(Box::new(move || {
                    //This is not allowed
                    err_sender.send(JsValue::from_str("foo"));
                    task.notify();
                }) as Box<FnMut()>);

                // TODO: handle cancellation with clearTimeout
                window().unwrap().set_timeout_with_callback_and_timeout_and_arguments_0(closure.as_ref().unchecked_ref(), 1000).unwrap();

                //Move to counting state
                self.state = CounterState::Counting {err_receiver} ;
                let task = current();
                task.notify();
                Ok(Async::NotReady)
            },
            CounterState::Counting {err_receiver}  => {
                if self.value == self.target {
                    Ok(Async::Ready(JsValue::from_f64(self.value as f64)))

                } else {
                    self.value += 1.0;
                    Ok(Async::NotReady)
                }
            },
            CounterState::Error (err) => {
                Err(err.clone())
            }
        }
    }
}

If I remove that line: err_sender.send(JsValue::from_str("foo")); then it compiles fine. But with that line, I can't seem to get around the trait constraints.

Any tips?

(I've left out the receiver polling just to keep the example a bit more concise - but we can imagine that polling it could move the state to CounterState::Error)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions