How to cancel first, outdate request if second was alraedy sent - javascript

I need to cancel first pending request if another was sent from the same service as the first is outdated already and there is no need to spend time on it as there will be two parallel request from same service.
Could you tell me ways how to do it?
It's GET request from service with #service decorator like:
this.service.get({ id: someId }).then(this.result)

You can't cancel a request from the client's side, once its fired.
You can cancel it from the server's side, once a new request arrives - and identify the duplicate using some key in the request headers or body.
The only thing you can do on the client's side - is ignore the response of the first request.

Related

Express not allowing more than one pending request from the same IP?

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.
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'});

Ignore response from a PUT call - javascript

I've a JS (Angular) client that makes a PUT request (REST API) to server and server sends back a large payload that I'm not using in the client currently.
Is there a way to just fire the request and ignore any response that comes back? The main need here is to avoid the data cost incurred by receiving that payload. I've looked at closing the connection once the request is fired, but am not sure if that's the best way to handle this.
If able, I think the only way to change this would be to change the api endpoint to not include a payload from the put request.
I'm assuming you are using angular's http class and using Observables. But even if you aren't, your angular client is going to need to read the response status sent back from the server to determine whether or not the put request was successful or not. In order to read the status, you'll need to response, and unfortunately the full response sent from the server.
You could close the connection right after the request, but as I've mentioned you'll have no way of knowing whether or not the request was successful.
To ignore the request just don't do anything if the request is successful.
If you don't want the request to exist at all then do it on the backend.

Provide Last-Event-Id to EventSource constructor

Is it possible to set the Last-Event-Id header of an EventSource ? I have a simple chat app that keeps the messages cached. When I connect, I send all the chat since the Last-Event-Id, or all of them if it is not provided.
Since I keep the messages, I figured I might be able to pass the Id to the EventSource constructor to avoid it giving me back all the messages I already have. Is that simply not possible ?
You can pass information on the query string.
var source = EventSource("source?eventId=12345");
Ultimately it is just up to you to make sense of it on the server side and return the correct event(s).
The EventSource request will only have the Last-Event-Id header if the connection breaks and the client will have to reconnect. You can "force" this reconnection by letting the server break the first connection.
It goes like this:
Create a connection using EventSource.
The server receives the request and test if the Last-Event-Id is a request header.
If the Last-Event-Id is present:
get the value/id.
send events from the server according to the id.
If the Last-Event-Id is not present:
send an event containing an id (the id that you consider to be the last id).
make the server break/finish the connection.
If the connection is broken by the server the client will try to reconnect with a new request. This time the request will have a Last-Event-Id header, and now you jump up to number 2.
The only problem with this approach is the delay caused by the client because it has to make two connections. I haven't tested the delay, but it looks like something around 3-5 seconds between each request.

Is it safe to invoke a AJAX call and let the browser cancel the request?

If I make a AJAX reqeust it will be displayed in the network tab in Chrome. If I in the same moment makes a client based redirect, the AJAX request will canceled. But will the request make it to the server and execute as normal? Is it something in HTTP/TCP that know's that the client has canceled the request? I don't think so, but I want to be sure.
If you're running PHP server-side, it will stop processing in the event of a client-side abort. (From what I've read, this isn't the case with other server-side technologies, which will continue processing after a client aborts.) See:
http://php.net/manual/en/features.connection-handling.php
But, it's best not to assume anything one way or another. The browser may cancel the request. And this cancellation may occur in time to stop processing server-side. But, that's not necessarily the case. The client could cancel at any stage during the request -- from right before the request is actually sent to just after a response body is sent. Also bear in mind, there are other things which can interrupt server-side request processing (hardware, power, OS failure, etc.). Expect some unpredictability.
From this, I'd make two recommendations:
Write your code be as transaction-safe as possible. If a request makes data changes, don't commit them until all changes have been piped to the database. And if your application relies on multiple AJAX requests to change some data, don't commit any of the changes until the the end of "final" AJAX request.
Do not assume, even if a request finishes, that the client receives the response. Off the top of my head, that means if your application is AJAX-heavy, always rely on client-side state to tell the server what information it has, rather than relying on server-side state to assume the client "knows" something.
This is one of the few cases where synchronous requests (async: false in the $.ajax(...) options) are appropriate. This usually avoids the browser from navigating to the other page until the request has finished.

Make ajax POST without requiring a response?

Is there a way to make an $.ajax POST request:
without requiring a response
so the server doesn't even try to return anything
Are there some HTTP headers to accomplish this? The goal would be to track statistics with minimal server and client request processing.
The server should return a HTTP/204 No Content response. That's as close as you can get.
If it is no problem in terms of security, and the amount of data you send is at maximum 2K minus the length of your URL, use a GET request instead. A GET request sends only one TCP packet, instead of two packets as a POST request does (first the header, then the data).

Categories