GithubHelp home page GithubHelp logo

Comments (4)

1c3t3a avatar 1c3t3a commented on September 2, 2024 1

Hi! That's an interesting question! In general the socket.io design is rather event driven, usually things happen as soon as the server sends an answer. Take a UI for example where a user clicks a button and a socketio Ack event is triggered. The user is informed about the outcome of the request (maybe with a popup), as soon as the server responds to the Ack. But nobody knows when this happens. Maybe the server needs to query a database or some other action with an undefined timespan happens.

Looking at the JS example you've provided you see the notion of a Promise as a return value:

public DescribePlayerSessions(request: DescribePlayerSessionsRequest):Promise<DescribePlayerSessionsOutcome> {

As you might know a Promise in JS resolves after some time and you could wait for the return value by subscribing to the Promise via the method then. The action you define there is then run after the promise is resolved (in the example context the server returns a response).

// Assume p1 is of the type Promise
 p1.then(
    function(val) {
      console.log("Promise fullfilled!", val);
    }
);

That's how it's done in Javascript. Rust itself has an async API (further information here) with a similar concept, the Future trait. A Future, similar to the Promise, also represents a value that might be available at some point in the future. The early versions of this crate also provided an async API, but I rewrote the crate in sync rust as this caused to much trouble for me (I wasn't and still am no async Rust pro).

So I think for your current situation there are two options: you could either wrap my emit_with_ack method and return a Future, or you simply use channels. An example of the above with channels would look something like this:

    let (tx, rx): (Sender<Payload>, Receiver<Payload>) = mpsc::channel();

    let ack_callback = |message: Payload, _| {
    println!("Yehaa! My ack got acked?");
    println!("Ack data: {:#?}", message);

    // send the result to the channel
    tx.send(message).unwrap();

    let json_payload = json!({"myAckData": 123});
    // emit with an ack
    let ack = socket
        .emit_with_ack("test", json_payload, Duration::from_secs(2), ack_callback)
        .expect("Server unreachable");

    // this operation blocks as long as no tx.send(...) was called
    let ack_result = rx.recv();

But note that in the current design of the library the ack callback never gets called when the server doesn't answer in time.

I hope that this is somehow helping you!

from rust-socketio.

1c3t3a avatar 1c3t3a commented on September 2, 2024 1

Hi @zamazan4ik, sorry for the delay. I thought about how to write this for a moment. The issues I had with async Rust were related to the fact that I was still learning rust when writing this crate (and I still am today). Introducing an async API just brought up too many new points for me. I might add an async API later, but not within the next time.

Concerning your specific problem: I think wrapping the call into a future is not really a nice way to do it, it adds a lot of complexity for no real value. I would rather rethink why you really need this value "after" the callback and not within the callback. Let me show you what I mean with an example:

let ack_callback = |message: Payload, _| {
    println!("Yehaa! My ack got acked?");
    println!("Ack data: {:#?}", message);

   // Why not do everything you want to do with the value here, as you're sure it's here already
   // if we're in the UI example, this would involve displaying a Popup
   if let Payload::String(msg) = message {
       Popup::new().set_message(message).show();
   }
};

let json_payload = json!({"myAckData": 123});
// emit with an ack
let ack = socket
    .emit_with_ack("test", json_payload, Duration::from_secs(2), ack_callback)
    .expect("Server unreachable");

// Why use the value here? You could move all code related to the servers message to the callback

This is what I meant by the abstract term 'event driven'. You use the value when you sure it's there, that's the basic idea of callbacks.

from rust-socketio.

zamazan4ik avatar zamazan4ik commented on September 2, 2024 1

Yeah, I understand the event-driven approach. Seems like in the referenced JS implementation an author tries to implement a "request-response interface with event-driven messaging". And for doing so the author just add timeouts :) I don't think that it's a nice way

So I think that the best approach here for me will be providing some kind of an API with providing a callback for such operations.

However, I will be happy to see an async version of your library. Seems like nowadays async Rust is quite stable.

Thanks!

from rust-socketio.

zamazan4ik avatar zamazan4ik commented on September 2, 2024

@1c3t3a Thanks for the so brief explanation! However, can you describe a little bit more, which issues you've found with async API for rust-socketio? I also was wondered, why rust-socketio has no async API.

About the way for returning a value from the callback. For me it's completely clear, how can I use the channel here (thanks for the example). But not sure, how I should properly wrap emit_with_ack into the Future trait. Can you give an example, please?

from rust-socketio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.