-
-
Notifications
You must be signed in to change notification settings - Fork 894
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
When to use Ajax Requests #369
Comments
At this point all major browsers on desktop and mobile support WebSocket, so this isn't really a strong argument anymore. I could accept it as valid if you had to write your own WebSocket client and server code, but all that work has been done for you with Socket.IO on both ends.
Socket.IO on the client side does this, and it is really nice. Clients have an exponential backoff algorithm to reconnect whenever a connection is dropped. With Ajax, you would need to do this yourself, or find a retry library that does it for you.
Okay, this one is harder.
Socket.IO establishes a point to point connection between the server and the client. Packets with information are written on this single connection. If you write a large packet and then a small packet, the small packet goes after the big one, they can't both go together because there is one connection. If you want both packets to travel at the same time, then you need the client to open two connections, exactly what the browser does when you send multiple Ajax requests concurrently. Also, large data packets in Socket.IO aren't a great idea. Consider "streaming" the data in small chunks. I believe that will solve your big + small packet problem nicely.
I don't understand this. In a Socket.IO connection there are no requests and responses in the HTTP sense, just events. If the client asks for something, it sends an event. The server then can block inside that event handler until it generates and sends the information, or it can just acknowledge the event and then spawn another greenlet to generate and send the data. I think the blocking situation that you have might be caused by your application, not by Socket.IO.
There is an option to request that all event handlers are spawn in their own greenlet. Pass
My rule of thumb is this: If you need small, frequent updates with low latency from client to server or from server to client, then Socket.IO is a good idea. Larger and/or infrequent messages, without a low latency requirement are probably better handled via HTTP requests. Hope this helps! |
Thanks for the quick response Miguel - you're a legend! Re: 1.) While I agree that socketio is stupid easy to use from a browser, connecting a standalone client without the browser is a bit harder. I've been using https://pypi.python.org/pypi/socketIO-client and it's a bit difficult. Socket.IO's docs are also really unhelpful as far as I can tell. Re: 2.) The retry behavior is definitely nice but in some situations it can shoot me in the foot - AFAIK there's no way to turn it off, and there's no way to know if an event was sent by a client while the server was alive or while it was down. Obviously you can work around it on the client-side by listening for the disconnect event but that means guarding all of your emits which is a pain. Re: 3.)
Is there a good example of this somewhere? I was looking at your flack application but I was hoping not to have to include celery.
Seems like this would include all basic user input to the server (I'm thinking button clicks / form submissions, not mouse position). So I guess I've overdone it a bit w/all of the events I'm sending from the client. Thanks again! |
I can't think of any direct example of this because I try to avoid long and expensive endpoints or events. If it is something simple, it's no problem to perform the work in the event handler, and it is something that cannot be reduced to one or more simple tasks, then Celery is usually more appropriate. But in any case, the idea of spawning a greenlet is really easy to implement. Say you have this event handler: @socketio.on('get_a_lot_of_data')
def get_data():
data = generate_a_whole_lot_of_data()
emit('data_for_client", data) If the def get_data_background(sid):
data = generate_a_whole_lot_of_data()
socketio.emit('data_for_client", data, room=sid)
@socketio.on('get_a_lot_of_data')
def get_data():
socketio.start_background_task(get_data_background, request.sid) The second thing you need to do, is make sure this long running function does not take the CPU for long periods of time. That means adding |
Okay sweet, thanks so much Miguel! |
Hey Miguel, thanks again for your help with my previous issues: #297 and #344 . Today my question is perhaps one you get a lot - when should one use a REST endpoint and when should you use a socket one?
Till now, my whole app's interface has been socketio. Recently I've been thinking about rewriting a lot of it to use REST. Here are my reasons:
1.) Compatibility: as more people & computers start using my app, http endpoints are simpler for them to work with. Unless they want to access a stream of data, running commands is easier w/a POST.
2.) Retries: part of the reason I am using socketio is because it allows me to take down my server and update it in the middle of running a job without inconveniencing connected clients. However, I've noticed that all events the client sends while the server is down are retried. This is really useful in some situations but it can cause the server to act on stale information.
3.) Hanging: here's a scenario that bugs me. When I load a page, a couple (currently socketio) events are fired: the client requests the state from the application, and it requests some data about the past. It takes an abnormally long time for the state to be displayed, and the history gets rendered at the same time as the state.
It seems like events on the socket are consumed sequentially. If I request a really big data payload followed by a small real-time update payload, the update payload doesn't get processed until after the data payload has been processed - so they render at effectively the same time. I'm not sure if it's a client or server issue but my hypothesis is that it's on the server side - basically, a new request greenlet is created for the http handler while the two socket events are handled by the same greenlet.
I guess what I'm asking is if you think these reasons for choosing AJAX are valid, and if not, what are some ways to use socketio to avoid these problems.
Thanks again,
Sam
The text was updated successfully, but these errors were encountered: