rust-socketio icon indicating copy to clipboard operation
rust-socketio copied to clipboard

Event handler lifetime shouldn't be static

Open doraeric opened this issue 2 years ago • 4 comments

https://github.com/1c3t3a/rust-socketio/blob/095db3a0e98cee5254ef32609222e036efb217d0/socketio/src/client/builder.rs#L169-L172

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 avatar Oct 08 '23 12:10 doraeric

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.

doraeric avatar Oct 08 '23 14:10 doraeric

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

1c3t3a avatar Oct 08 '23 15:10 1c3t3a

@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");
}

vishalcjha avatar Nov 07 '23 23:11 vishalcjha

@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`

HuakunShen avatar Apr 27 '24 03:04 HuakunShen