2

Using Angular's http client with complete in the subscribe (or the finalize pipe), the code is never executed.

Simple example:

this.http.get(myUrl).subscribe({
    next: results => handleSuccess(results),
    error: err => handleError(err),
    complete: () => handleAllRequests()

The handleAllRequests() function is never called. Adding the finalize pipe or an additional `.add() after the subscription per other answers does not work.

Similar questions: Angular 6 / Rxjs - how to basics: observables success, error, finally Angular HttpClient observable not completing

Wayne F. Kaskie
  • 3,257
  • 5
  • 33
  • 43
  • 1
    Angular http client `get` method returns an Observable that either `complete`s automatically after the first notification or `error`s (see [here](https://angular.io/guide/http#using-interceptors-to-request-multiple-values)). So you must have an issue somewhere else. – Picci Jan 10 '23 at 09:34

2 Answers2

2

After some digging, I found the answer to be simple but not obvious (to me at least).

It came down to understanding when an observable "completes". As long as the subscription existings (is not unsubscribed or observer.complete() is not called), the complete code and finalize pipe are not called.

Therefore, you must "complete" the subscription. With Angular http client, I chose to use take(1) which will complete the subscription after one execution. I use this pattern frequently for http requests as it is normally the goal to make the request once in the first place.

While the above is true, I found that my real issue was that a teammate added an interceptor with a switchMap that was not completing, which effectively caused every HTTP request to remain incomplete unless forced like the suggestion above (using a take(1), etc.)

I hope this helps!

Wayne F. Kaskie
  • 3,257
  • 5
  • 33
  • 43
  • 3
    Keep in mind that `error` and `complete` messages can occur only once during the subscription of an observable and only one of them can occur. So if an error occurs, `complete` will not be called. – riorudo Jan 10 '23 at 08:04
  • The `complete`-handler will also not be run, if you unsubscribe in the `next`-handler. Another reason could be interceptors, but Angular's `HttpClient` will usually complete after the first emission (unless you observe upload progress or similar). – Lukas-T Jan 10 '23 at 08:19
  • @Drenai, that's what I thought...which is why finding the answer was elusive. It does NOT complete on success (I didn't test it with error). So you need a take(1) or first() or unsubscribe, etc. – Wayne F. Kaskie Jan 12 '23 at 16:30
  • There's definitely something up with my app. None of the HTTP requests are completing. Since posting this, I've had to field several other bugs resulting from HTTP requests NOT completing as expected. – Wayne F. Kaskie Jan 19 '23 at 02:14
  • Oh wow, I had the exact same issue once, where I was that teammate at the same time :D – hogan Feb 09 '23 at 08:57
  • lol It's not a bad thing, just one more place to know to look. – Wayne F. Kaskie Feb 17 '23 at 14:37
0

I know its a bit confusing, usually you need to complete the subscription somehow. In the end an observable is something you observe until you are done - and this is usually not upon the first message. So you need to say that you are done.

In these cases I usually use take(1), or first().

But Angular's HttpClient does this already under the hood. So maybe you are testing with another Observable that you created (and not HttpClient) or maybe (just an assumption) there is an error in your syntax (i.e. brackets).

hogan
  • 1,434
  • 1
  • 15
  • 32
  • That's what I thought, but it's not the case. Maybe it changed in the latest versions, which is why I had to post the question. Test it out with ng15 and rxjs: 7.5.6 – Wayne F. Kaskie Jan 12 '23 at 16:31
  • I tested with ng15.1.1 and rxjs 7.5.6 and it works for me. This is how my component code looks like: test = this.http.get('https://www.swapi.tech/api/people/1').subscribe({ next: results => console.log('result: ....', results), error: err => console.log('errrrrrr'), complete: () => console.log('i am done'), }); constructor(private http: HttpClient) {} – hogan Jan 13 '23 at 13:48
  • btw stackoverflow automatically removed/hide the 'h t t p s : / / w w w .' in the url, you would have to add it manually. – hogan Jan 13 '23 at 13:50
  • So odd. I put this test code in my app and it didn't resolve itself until I add forced it to complete with a take(1). I created this stackblitz and it works as I expect it to. https://stackblitz.com/edit/angular-ivy-awbs83? I'm going to do some digging to find out what the issue source is. – Wayne F. Kaskie Jan 13 '23 at 21:58
  • I commented below as well, but there is something going on where none of the httpClient requests are completing in the app. I'm digging around to find out why. – Wayne F. Kaskie Jan 19 '23 at 02:15
  • hmm, maybe removing node_modules and reinstalling fixes your issue. seems like something is broken. also you need to import httpClientModule, right.. – hogan Jan 23 '23 at 14:04