I'm making a chat application that uses long polling with express (I'm aware websockets are better for this, I just wanted to make something specifically with long polling).
This is the code that the client sends a GET
request to when it's waiting for a new chat message:
app.get('/api',(req,res)=>{
listeners.push(res)
})
It pushes the response objects to an array, and once a new chat message is available it calls .send()
on the responses. When the client recieves the response, it sends a GET
request again, waiting for new messages.
Here's the code for when someone sends a message (simplified)
app.post('/api', (req,res)=>{
listeners.forEach(listener=>{
listener.json(req.body)
})
listeners = []
res.status(200).end()
})
I noticed that when I open two tabs of my site, only the 1st tab's request gets put in the array at first. That makes the 2nd tab not receive the 1st chat message. The 2nd tab's request only gets pushed into the array after the 1st chat message. So when the second chat message is sent it works fine. This means that the 2nd tab is always one request behind.
Here's an example in case that wasn't clear:
Client 1 connects
Client 2 connects
---
Client X sends a message:
Client 1's request 1 receives the message
Client 2's request 1 is still pending
---
Client X sends another message
Client 1's request 2 receives the message
Client 2's request 1 receives the message
---
Client X sends another message
Client 1's request 3 receives the message
Client 2's request 2 receives the message
...
Another thing I noticed is that when I restart the server after client 1 and 2 connect, client 2's request get pushed into the array after the restart.
Could someone explain this behavior? Thanks in advance.
CodePudding user response:
This sounds like the browser is hoping to use a cached request so it waits for a previous request with the exact same URL to see if it can use the cached result rather than firing the same request again.
You can test this hypothesis by adding a unique query parameter to every request as that will disable any attempts at caching since they would all be different URLs.
Or, if these requests are sent using the fetch()
api in the browser, you can directly tell that API to not use caching with the cache: 'no-cache'
option as in:
const response = await fetch(url, {cache: 'no-cache'});