Comments (4)
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.
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.
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.
@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)
- EngineIO does not timeout on missing pings
- Event handler lifetime shouldn't be static HOT 4
- Add feature to use rustls instead of native-tls HOT 1
- Buffer is not supported when it's a field in an JS object? HOT 2
- Manual disconnect doesn't block reconnecting HOT 1
- Add support for WebTransport HOT 2
- add macro to simplyfy async callback define HOT 4
- Allow async connections to update auth when reconnecting HOT 4
- [feature request] custom-parser support HOT 5
- Unable to cross-compile for android HOT 1
- Multiple payload still broke HOT 2
- when using binary buf data with emit_with_ack function callback is not executed
- Is it possible to add `.on()` event callback after connect like in JavaScript? HOT 1
- Unable to use shared variable in async callback HOT 4
- Binary Data event names incorrectly handled HOT 1
- Introduce Custom shared data structure
- [bug] unable to connect to an http based socketio server HOT 2
- Help
- Does it support rooms in SocketIO ? HOT 1
- Async client is not notified of (unexpected) websocket transport close
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust-socketio.