InterLinked
InterLinked

Reputation: 1403

How to send AJAX messages to websocket users

I've implemented realtime chat in Websockets and it works just like a charm. I did it side by side with AJAX polling (which existed before), as I didn't want to remove AJAX polling support for older browsers, so although Websockets will be preferred, I am keeping polling as an option.

The way I have the websocket code set up is to:

The way the AJAX send works is:

The way the AJAX poll works is:

I have more of a conceptual question about how to get the two to work with each other. Assume I have User A and User B. If User A and User B are either both using AJAX polling or both using websockets, there are no issues whatsoever. It works as you would expect. But take the case when User A is using websockets and User B is using AJAX polling.

A → B

B → A

This is what I'm hung up on. Websocket -> AJAX user messages work because the message ends up in the database where it can be polled by an AJAX user. But websocket users don't poll the database at all, so messages from AJAX users have no way of getting into the pipeline. Currently, websocket users don't see any messages from AJAX users. They only see them if they do a full page reload, at which point all messages get retrieved directly from the database.

What would be the appropriate method to allow some way for messages from AJAX users to get sent out via websocket to relevant websocket users? Basically, how can I communicate in the other direction?

The only thing I've been able to find on this subject is this slideshow - however, I'm not using longpolling, and I'm not entirely sure what it means by "providing that" to the websocket app. Does that mean put the onus on the websocket server to check for new AJAX messages? Is there no way to "push" from the AJAX script to the websocket server?

Upvotes: 1

Views: 395

Answers (2)

InterLinked
InterLinked

Reputation: 1403

Thanks to ADyson for some ideas on how to approach this. This is what I ended up doing:

I have my JS clients ping the server every few seconds. For AJAX users, it's more frequent because they need to poll for messages. For Websocket users, they don't need to poll for websocket messages, so they poll every 15s to "check in". This has the benefit of functioning as an infinite loop essentially for each client, which is exactly what the idea requires.

What I did was essentially add a column to the messages table that keeps track of the message source: 0 for AJAX and 1 for WebSocket. Then, I modified the function that retrieves messages to take in an $ajaxOnly parameter. When I call this on an AJAX poll, it's false. For websocket polls, I call it with true instead. The result is for all rooms a user is in, it polls the DB and checks if there are any new AJAX messages. If there are, it sends them back to the client.

There are 2 caveats:

  • Messages will appear out of order. Websocket messages are relayed in realtime, so an AJAX message sent before a Websocket message could appear earlier to another AJAX user but later to other Websocket users.
  • This is not realtime. It's as slow as your poll interval, which in my case is 15 seconds for websockets since polls are very DB-intensive. AJAX polls are more frequent because they need to be to get any messages at all.

This isn't a perfect solution, but it does meet the goal of allowing AJAX messages to show up for websocket users in near-realtime. For me, I wanted to fully support AJAX and WebSocket, but AJAX is more for compatability and ideally most people will use WebSockets, so the fact that this isn't a great solution doesn't concern me too much, since it does get the job done.

If you were hoping for a realtime solution (like I was), you're going to be disappointed by this, but this is at least a workable solution so I've adopted it until something better comes up. You can make it near-realtime by increasing the frequency with which clients ping your server.

Upvotes: 1

MRonline
MRonline

Reputation: 203

Simple solution: When you save the message into the Datebase, push it to the Websocket Clients as well.

Upvotes: -2

Related Questions