3

I found this answer where the solution proposed is to use Observables to set http requests' timeout.

However my code is structured to use mostly promises (I use observables where I want to have data automatically updated - that's not the case of the API calls).

Here is my code (inspired by Angular 2 tutorial):

makePostRequest(requestUrl:string, requestBody: any, requestOptions?: RequestOptions): Promise<any> {
    requestOptions = requestOptions || new RequestOptions({ headers: this._defaultHeaders });
    return this._http.post(requestUrl, JSON.stringify(requestBody), requestOptions)
        .toPromise()
        .then(this.extractData)
        .catch(this.handleError)
}

How to set a timeout and throw an error (if the timeout expires) that I then catch in .catch() or - alternatively - replicate the exact precise behavior with Observables (including converting the result to a Promise and not monitoring for monitoring for API update(*))?

(*) NOTE: I'm not sure whether Observables keep calling the APIs to check for new data, but that's not the point of my question, I just want to make sure this behavior does not occur.

3 Answers 3

3

I would expect this to do what you want (not tried):

makePostRequest(requestUrl:string, requestBody: any, requestOptions?: RequestOptions): Promise<any> {
    requestOptions = requestOptions || new RequestOptions({ headers: this._defaultHeaders });
    return this._http.post(requestUrl, JSON.stringify(requestBody), requestOptions)
        .timeout(3000, new Error('timeout exceeded'))
        .toPromise()
        .then(this.extractData)
        .catch(this.handleError)
}

From Angular2 timeout in http post request

Sign up to request clarification or add additional context in comments.

5 Comments

already tried that. apparently timeout is supported only by observables
And that doesn't work? Here is explained how to timeout a Promise stackoverflow.com/questions/32461271/… I don't know how to use it in your case because you aren't creating the Promise. You would need to do something like return new Promise((resolve, reject) => { http.post().subscribe(... resolve(), error => reject())})
I don't remember the exact error in this specific case but I remember the cause : timeout is valid only in a observable chain, without promises.
I'll make some other try next days. for now I'll up vote for the effort :)
I found a solution (I answer to my own question). your answer was almost correct. But the right requence is first map, then toPromise and finally catch, taking care of importing the necessary rxjs operators.
2

The solution (right chain + imports) I found:

// ! must import these
...
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';

return this._http.get(requestUrl, requestOptions)
        .timeout(5000, new Error( 'HTTP (GET) timeout for path: ' + requestUrl))
        .map(this.extractData)
        .toPromise()
        .catch(this.handleError);

Comments

0

I approached this a bit differently. I had logic that relied on a promise being returned—and doing .timeout caused it to immediately fail regardless of the timeout duration.

My solution was to create a new promise instead of using toPromise:

const timeoutInMs = 3000;

const request = this._http
    .post(/* ... */)
    .timeout(timeoutInMs);

return new Promise((resolve, reject) => {
    request
        .take(1)
        .subscribe(
            data => resolve(data),
            error => reject(error),
        );
});

If you use this a lot, you could refactor it into a function (not yet tested):

const toPromiseWithTimeout = <T>(obs: Observable<T>, ms): Promise<T> =>
    new Promise<T>((resolve, reject) => {
        obs
            .timeout(ms)
            .take(1)
            .subscribe(
                data => resolve(data),
                error => reject(error),
            );
    });

And to use it:

const timeoutInMs = 3000;

const request = this._http
    .post<ResponseType>(/* ... */);

return toPromiseWithTimeout(request, timeoutInMs);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.