We have a page with multiple requests to the backend REST with big delay and much calculation time on the server side, that makes a user to wait for a long time until all queries respond, then run other requests no matter whether new queries are fired by the actions on the page itself.
If it does not matter whether that page or state changes it, then I would like to cancel the pending requests.
I can cancel each pending request by using $cancelRequest() function from ngResource#1.6.6.
Answer
How to implement automatic resourceInstance.$cancelRequest() on $rootScope.$on('$stateChangeStart')
Used
place $resourceProvider.defaults.cancellable = true; in
app.config($resourceProvider)
Service/Factory to return an instance of $resource
ngResource#1.6.6
angular#1.6.6
Related
I have a website that continuously makes AJAX requests (about 1 per second).
I would like seleniumwire to simply keep the browser open and catch all these requests, without having to refresh the page, but I couldn't find a way to do it, i.e.
for request in driver.requests:
...
will return the requests made while loading the page, but not all subsequent requests, even if I try to use:
chrome_options.add_experimental_option("detach", True)
Is there a way to keep seleniumwire catching AJAX requests continuously on a loaded web page?
Just found the solution myself: I need to use an interceptor:
def interceptor(request, response):
print(
request.url,
response.status_code,
response.headers['Content-Type']
)
driver.response_interceptor = interceptor
Then I can simply do time.sleep(1000000) after driver.get(...) and wait for responses to arrive.
I have a react-redux application which:
Loads N records from the database depending on a "limit" query parameter (by default 20 records) on first application load (initialization)
Every 10 seconds app requests same (or newer) records from the database to update data in real time
If a user changes filters - app requests new records from the database according to the filter and re-renders app (+ changes interval to load data according to the filters)
If users scrolls down, the app automatically loads more records.
The problem is that if a user for and instance tries to filter something out and at this same time interval is loading more data, 2 requests can clash and overwrite each other. How in react-redux app I can be sure in a request sequence. Maybe there is a common approach on how to properly queue requests?
Thanks in advance!
I am not sure what you mean by 'clash'. My understanding is that the following will happen:
Assuming that both requests are successful, then data is retrieved for each of them, the redux state will be updated twice, and the component which renders the updated state will render twice (and the time passed between the two renders might be very short, which might not be very pleasant to the user)
If you want only one of these two requests to refresh the component, then a possible solution may be the following:
Each request starts, before retrieval of data from the database, by creating a 'RETRIEVAL_START' action. 'RETRIEVAL_START' will set a redux state variable 'retrievalInProgress'
If you want, in such a case, to get results only from the 1st of the two requests, you can check, before calling the action creator from the component, if 'retrievalInProgress' is on. If it is, don't call the action creator (in other words, do not request data when a request is in progress). 'retrievalInProgress' will be cleared upon successful or failed retrieval of data.
If you want to get results only from the 2nd of the two requests, then make 'retrievalInProgress' a counter, instead of a boolean. In the 'retrievalSuccess' action of the reducer, if this counter is higher than 1, it means that a new request already started. In this case, do not update the state, but decrement the counter.
I hope that this makes sense. I cannot be 100% sure that this works before I test it, which I am not going to do :), but this is the approach I would take.
All of the solutions I've found while searching react to a 401 response from an API call before triggering logic to refresh the expired token. In my case, I'm using react-cognito which puts the expiry time in the redux store under cognito.user.signInUserSession.idToken.payload.exp (integer representing unix time).
I would like to try and implement a scheme where expiry is pre-empted and I'd like to keep this logic separated from my API call code, if practical.
One option I explored is setting a timeout for currentTime - expiryTime - someBuffer, but this may be 50 minutes long or more and I've read that long-running timeouts can often be unreliable, having strange performance especially when the browser tab is not in-focus.
Another option I considered was a saga that runs in a loop, initiated by the LOGGED_IN action and ended by the LOGGED_OUT action, that checks for an almost expired token and refreshes it. On mobile, my understanding is that code execution is paused while the browser is in the background - as such this approach would have an edge case where if the user foregrounds the browser just after token expiry then there's a window of time equal to the loop interval where API calls will 401. The loop interval can be made smaller but the edge condition could never be eliminated.
Is there some scheme that can reliably fire an event/action just before token expiry or, in the case of mobile browsers, fire immediately upon execution-resume if foregrounding happens after the desired refresh time?
Thanks!
David
There is no need for long lived timeouts, simply check each second or so if the token has expired.
while(true){
yield delay(5000);
if(yield call(checkExpiring)){
yield relogin();
}
}
There will be a lot of checks, but they don't have any real performance impact.
That said, I usually write a fetch middleware which checks if the server replies with 401/402 and than reauthenticate and resubmit with the new token.
If I call an async data store operation such as the one shown below but then end the request without calling get on the future, what will happen?
Will my operation still execute?
Will me response be sent before the operation has completed execution?
AsyncDatastoreService datastore = DatastoreServiceFactory.getAsyncDatastoreService();
Entity entity = new Employee("Employee", "Alfred");
// ... populate entity properties
// Make a sync call via the async interface
datastore.put(key)
//Return response
The rpc will be sent immediately; when your app is ready to send a response to the client, it will block until the rpc is done.
I've done this in python by accident and the result was nothing was written to the datastore.
Your operation may still execute but it seems that'll happen only if the response handler is still active when it decides to execute. If not, nothing seems to happen at all.
Yes, the response will be sent before the operation has completed execution - this is the main feature of a future, it's non-blocking.
I am calling an asynchronous service from my Silverlight app and I want to be able to cancel that call after it is made. There is an option for e.Cancelled once the service has finished (i.e. If e.Cancelled Then), but how to you set that cancelled to true after you have called it? How do you cancel that asynchronous call?
Let me clarify a bit... what I am trying to do is call the SAME method twice, one right after the other, and get the results of the last call into my collection. If I call an asynchronous method twice there is no guarantee that the second call will return first, so I may end up with the results of the first call coming in last and having the wrong results in my collection. So what I would like to do is cancel the first call when I make the second so I don't get results back from the first call. Seeing as how there is a Cancelled flag in the completed event args I figure you should be able to do this. But how?
It's async... the transfer is passed off to a remote server and it does not return until the server is done with it.
Basically the server will keep going, but you don't have to wait for the response. Disconnect your service completed event handler and pretend it was never called. That will give the effect of cancelling the operation.
If you really need to cancel something in progress on the server you would need to make another call to the server to cancel the first call. Assuming the first call is a very slow one, this might be possible.
Update (as question changed)
In the case you specify, it will be up to the server to cancel a operation in progress if a second one comes through, not up to the client. e.Cancelled is set server-side.
However... :)
You have exposed a client usability issue. Shouldn't you also delay sending any service request until an idle delay has passed. That way rapid selections will not result in multiple service calls.
Also... :>
You may also want to send a sequence number to your service calls and return that as part of the result. Then you will know if it is the latest request or not.
It sounds like what you really want to do is ignore the responses of all but the most recent call.
Set a unique ID (could be request #, a Guid, timestamp, or whatever) with the request, and make sure the service sends that same value back. Keep around the ID of the most recent request and ignore response that don't match that ID.
This will be safer than cancelling the first request, since if the service has already started sending the response before the cancel request happens, you still get your error condition.