I am making a API call but sometimes it is taking more time to get the response. I want to set a specific amount of time, lets say "8secs", to wait for the response if the time mention before has pass the API call should stop and show in console "ERROR time out".
I have tried adding the timeout in a pipe as other posts says like this:
`this.http.post<RefreshTokenResponseMessage>(url, tokenRequestMessage, { headers }).pipe(timeout(20)).toPromise()`
but it is showing an error with the timeout there.
I also try adding the timeout param in the header like this:
`const headers = new HttpHeaders({authorization: 'Bearer ${sessionstorage.getItem('authData')}',timeout: '${2}',});
return this.httpClient.get(URL, { headers });`
But I am also facing the same issue that it is not triggering the error.
Has anyone encounter something like this?
If you want to output a console.error if the http response has not arrived after 8 seconds, you can do this as follows:
this.http.post<RefreshTokenResponseMessage>(url, tokenRequestMessage, { headers }).pipe(
tap((res) => console.log('Result:', res)),
timeout(8000),
catchError(_ => {
console.error('ERROR time out');
return EMPTY;
})
)
.subscribe();
Related
I am using axios.interceptors and useContext to handle the request loading spin component in my React.js project.
When the request start, I set the context value - showLoading true, and change to false if it finished or error. The function works perfectly. Here is my sample code:
// Request
axios.interceptors.request.use(request => {
setGlobalLoading(true)
return request;
}, error => {
setGlobalLoading(false);
return Promise.reject(error);
});
// Response
axios.interceptors.response.use(response => {
setGlobalLoading(false);
return response;
}, error => {
setGlobalLoading(false);
return Promise.reject(error);
});
However, I have a page which is a table, and it need to call multiple api on each row, and all the api return so fast. Then it make the loading component "blinking".
So I have an idea, can I make "Only show the loading if the request take more than 1 second " or I should set the delay to close the loading? (But I don't know how to get any pending requests, because this may close the loading when another request not finish)
The callback function only call once, should I use the context or state to save the setTimeout and clearTimeout functions? or any better solution to handle this case?
you can create a array to save requset.
Usually request has a request id,you can use this request id.
if you send a request ,you can push request to array,in finally you can remove this request .
if this array.length >0 loading is show .else loading is close
I'm using Angular's HttpClient to make HTTP requests and I'd like to specify a timeout for them.
I know I can use HTTPInterceptors and add a timeout to RxJS operators, however, these apply to the whole request which I don't want to abort if data transfer is in progress, only if the browser is hanging while trying to connect.
The kind of timeout I need is available in Node.js for example which is well explained here:
Let's say you called socket.setTimeout(300) to set the timeout as 300
ms, and it took 100 ms for DNS lookup, 100 ms for making a connection
with a remote server, 200 ms for the remote server to send response
headers, 50 ms for transferring the first half of the response body
and another 50 ms for the rest. While the entire request & response
took more than 500 ms, timeout event is not emitted at all.
Is it possible to have a timeout like this in an Angular app?
I looked at the source code for the HttpClient. The code that actually deals with the underlying XMLHttpRequest is the class HttpXhrBackend, in source file named xhr.ts
Unfortunately, HttpXhrBackend just uses the default settings of XMLHttpRequest, and does not provide a way to set the XMLHttpRequest's timeout value.
I have seen suggestions for using RxJS operators to shorten the effective timeout,
but that's a bit of a hack, and doesn't really do what you are asking for.
So, technically, the answer to your question is "No", not with the stock Angular HttpClient, but I suppose that you could create your own implementation of HttpBackend and attempt to inject that.
P.S. This article shows how to provide a custom HttpBackend implementation.
For those still seeking a 'hacky' solution you can create an observable and insert an empty/failure after your desired timeout period:
handleError(error: HttpErrorResponse) {
console.warn('HTTPErrorResponse caught', error);
return observableOf({});
}
async __sendCommandHTTP(cmd: SoftAPCommand) {
const URL = this.options.host + cmd.name;
let result: SoftAPResponse = {
name: cmd.name,
payload: {},
error: false,
};
this.logger.debug('[softap-setup starting request');
await new Promise(resolve => {
const httpEvent: Subject<any> = new Subject<any>();
let returned = false;
const sub = this.http
.get<any>(URL, {})
.pipe(catchError(this.handleError))
.subscribe(data => httpEvent.next(data));
// Our cheeky method to ensure a timeout
setTimeout(async () => {
if (!returned) {
this.logger.info('[softap-setup] timeout on ' + result.name);
httpEvent.next({});
}
}, 5000);
httpEvent.subscribe(data => {
this.logger.info('[softap-setup] response ', data);
returned = true;
switch (cmd.name) {
case 'scan-ap':
if (Object.prototype.hasOwnProperty.call(data, 'scans') && data.scans.length) {
result.payload = data.scans;
} else {
result.error = true;
}
break;
default:
result.payload = data;
break;
}
httpEvent.complete();
resolve();
});
});
return result;
}
Basically either the response or the timeout flags there has been a result. The handleError function also neatly handles any eventual errors that may come along, ie the host isn't available. You could apply other logic in there or even pass along the HTTPErrorResponse object.
I have an Ajax call that validates an input data and show the response to the user. It usually takes less than five minutes to run and send the response, but it may vary depending on how much data I'm validating. When I run from my computer, I always get the response, but when the client runs the same application from his computer on his network, he never gets an answer. So he waits ten minutes without an answer and then press F5 to get the validation log.
I am using VueJS and below is my request.
this.$http.get(url).then(
response => {
console.log("success");
},
error => {
console.log(error);
}
)
.finally(function(){
console.log("finally");
})
.catch(function(err) {
console.log(err);
});
We're both using Chrome and looking at his console, none of the above logs are shown and there are the following errors: net::ERR_CONNECTION_RESET, net::ERR_NETWORK_CHANGED, net::INTERNET_DISCONNECTED.
Is there a way to force an answer without specifying a timeout? Are those errors above related to the problem? If so, how can I fix them?
I'm trying to make a fetch request that takes a long time (2-5m), but I'm getting this error message in the Chrome console after around 1m30:
Failed to load resource: net::ERR_EMPTY_RESPONSE
So, I tried to wrap my XHR request in a timer, like that:
client-side code:
xhr.open('GET', '/refresh', true);
xhr.timeout = 600000;
xhr.onload = function () {
window.location.reload();
};
xhr.send(null);
server-side code:
app.get("/refresh", (req, res) => {
var process = spawn('python3', ["scrape.py"]);
process.stdout.on('data', function (data){
console.log("-> " + data.toString());
if ((data.toString().indexOf("done") > -1)) {
res.json({done: "done"});
}
});
});
But I'm still getting the same error after around 1m30, and also the console log 'TIMEOUT'.. Why?
If I run the exact same code with a Python script that lasts 20 seconds, it works perfectly.
Thanks
To prevent the browser from timing out due to lack of response, you must send it a response within the timeout (sounds like 90s based on your test). This means your application most likely needs to be redesigned. Since it doesn't look like you're using websockets, everything is stateless and synchronous on the server, so you will have to make the requests pseudo-asynchronous by hand:
The historical pattern is to:
Spawned process writes its result somewhere
The server should return a token (/refresh?token=1234) where when requested, returns the result when the result is ready, otherwise returns something like status 204.
Return the token in the initial response
In your client, your timeout keeps checking the token, if status == 204, reset the timer, otherwise you have the complete response and break out of the timer.
I am getting error with status 302
But while trying to log error in catch I am getting 200
post(url, data, successCallBack, errCallback) {
return this.http.post(apiDomain + url, JSON.stringify(data), {
headers: this.headers
}).catch(this.handleError).subscribe(
(res) => {
successCallBack(res.json());
},
(err) => {
errCallback(err);
}
);
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status;
console.log(error.status); // log is 200
console.log(error)
console.error(errMsg);
return Observable.throw(errMsg);
}
Requirement I want to send another post call on redirect URL redirects.
How to get Redirect URL.
Need help.
Late answer I know, but for anyone stumbling across this.
The short answer is you can't as the browser handles 302's itself and won't tell angular anything about that. What you can do is set-up an interceptor style class that monitors what is going on.
Google for angular2 http interceptor or similar, it's a little beefier than your example above and can monitor every XHR connection. An example is here:
https://www.illucit.com/blog/2016/03/angular2-http-authentication-interceptor/
What this now allows is that any connection will come through your interceptor. As we won't be able to monitor 302s, we have to think about what might happen. For example in my example the request suddenly changes the url to something with my auth in it.
Great so my 1st bit of pseudo code would be:
if (response.url.contains('my-auth string')) {
redirect....
}
I can also see on the headers provided that instead of application/json I've suddenly gone to text/html. Hmm, that's another change I can check for:
if (response.url.contains('my-auth string') && response.headers['content-type'] == 'text/html') {
redirect....
}
You may have other parameters you can check, however these were good enough to detect a redirect for me. Admittedly this is with respect to being redirected to login and not another example, hopefully you get enough distinct changes check for you to decide whether you have got a 302.