Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event handler lifetime shouldn't be static #363

Open
doraeric opened this issue Oct 8, 2023 · 4 comments
Open

Event handler lifetime shouldn't be static #363

doraeric opened this issue Oct 8, 2023 · 4 comments
Labels
good first issue Good for newcomers help wanted Extra attention is needed

Comments

@doraeric
Copy link

doraeric commented Oct 8, 2023

pub fn on<T: Into<Event>, F>(mut self, event: T, callback: F) -> Self
where
F: FnMut(Payload, RawClient) + 'static + Send,
{

Currently, when building client with event handler, the lifetime of the event handler is required to be static, but I think it should be as long as the client instance.
I want to pass some objects, queue for example, to handlers without transferring ownership. It seems impossible at the moment.

This is the code that I want to use

{
    let (tx, rx) = channel::<String>();
    let callback = |payload: Payload, socket: RawClient| {
        tx.send("...");
    };
    let callback2 = |payload: Payload, socket: RawClient| {
        tx.send("...");
    };
    let socket = ClientBuilder::new(url)
        .on("evt1", callback)
        .on("evt2", callback2)
        .connect()
        .expect("Connection failed");
}
@doraeric
Copy link
Author

doraeric commented Oct 8, 2023

I just found that crossbeam_channel works for me since the sender can be cloned. But I still think the handler should have shorter lifetime.

@1c3t3a
Copy link
Owner

1c3t3a commented Oct 8, 2023

Fair point! Didn't think about this in the implementation. I am very happy to accept a PR for this!

@1c3t3a 1c3t3a added help wanted Extra attention is needed good first issue Good for newcomers labels Oct 8, 2023
@vishalcjha
Copy link

@doraeric In your example, you are missing move for tx. Once you do that it should work.

{
    let (tx, rx) = channel::<String>();
    let tx_clone = tx.clone();
    let callback = move |payload: Payload, socket: RawClient| {
        tx_clone.send("...");
    };
    let callback2 = move |payload: Payload, socket: RawClient| {
        tx.send("...");
    };
    let socket = ClientBuilder::new(url)
        .on("evt1", callback)
        .on("evt2", callback2)
        .connect()
        .expect("Connection failed");
}

@HuakunShen
Copy link

@vishalcjha How to transform your example code to use async? I had a lot of trouble with this.

For example

#[tokio::main]
async fn main() {
    let (tx, rx) = channel::<String>();
    let tx_clone = tx.clone();
    let callback = |payload: Payload, socket: Client| {
        async move {
            tx_clone.send("...".to_string());
        }.boxed()
    };
    let callback2 = |payload: Payload, socket: Client| {
        async move {
            tx.send("...".to_string());
        }.boxed()
    };
    let socket = ClientBuilder::new("")
        .on("evt1", callback)
        .on("evt2", callback2)
        .connect()
        .await
        .expect("Connection failed");
}

Always gives error:

expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
this closure implements `FnOnce`, not `FnMut`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants