Return an Empty Observable

Return an empty Observable

Since all the answers are outdated, I will post the up to date answer here

In RXJS >= 6

import { EMPTY } from 'rxjs'
return EMPTY;

how to return an empty observable

Observable.of() should work for your case:

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
// or import {Observable} from 'rxjs/Rx';

return Observable.of();

or

import {EmptyObservable} from 'rxjs/EmptyObservable';

return new EmptyObservable();

Handle http error using switchMap and return empty Observable

First option is to complete an observable sequence, i.e.

.pipe(
switchMap(_ => this.httpClient.get<IUserInfo>(`/users/{id}`))
catchError(userInfo => {
// Do something with error, like log, etc
return empty()
})
)

in this case, if previous observable (httpClient) throws an error, it will be completed, ie subscription section will not be reached... Ideal case in your case

Second option is to return predictable results, for example if endpoint returns an array, you can return an observable of empty array

.pipe(
switchMap(_ => this.httpClient.get<IUserInfo>(`/users/{id}`))
catchError(userInfo => {
// Do something with error, like log, etc
return of({})
})
)

Third option is to property handle error in subscriber, but it will not be your case as long as you use async pipe

.pipe(
switchMap(_ => this.httpClient.get<IUserInfo>(`/users/{id}`))
)
.subscribe(res => {}, err => {
// return predictable results here
})

Although I'd recommend to achieve this with ErrorHandler Interceptor and additional checks. Error handler interceptor will catch all server error and handle error accordingly.. In your case you also can prepend api origin via interceptor, so you don't have to add it manually to each service

@Injectable({
providedIn: 'root'
})
export class ApiInterceptor implements HttpInterceptor {
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Appending environment.origin only if url is not starts with protocol
if (!req.url.match(new RegExp('^https?://'))) {
req = req.clone({
url: environment.origin + req.url
});
}

return next.handle(req).pipe(
catchError(error => {
if (error instanceof HttpErrorResponse) {
// Do something with an error here
}
return throwError(error);
})
);
}
}

.pipe(
switchMap(_ => this.httpClient.get<UserInfo>(`/users/{id}`)),
map(userInfo => !userInfo || typeof userInfo !== 'object' ? {} : userInfo),
catchError(err => empty())
)

Also, get through TypeScript Coding Guidelines . IUserInfo is not complied with it...

How to test if returned Observable is EMPTY

It seems that we have a specific operation in RxJs that checks if an observable is empty. The operation is isEmpty()

it('should return EMPTY when ...', (done) => {
actions$ = of(someAction)
effects.effect$.pipe(isEmpty()).subscribe( (res) => {
expect(res).toEqual(true)
done()
});

res will be true only if observable does return with empty

Subscribe callback not called when empty Observable returned

Observables act differently to promises. The RxJS EMPTY Observable doesn't call the 'success' callback, only the 'complete' callback. The done function should be called in 'complete' rather than in 'success':

funcToTest().subscribe({
success() { /* Called when 'x' is returned, e.g. after the subscriber calls 'next' */ },
error(err) { /* Called on an error. */ },
complete() {
/* Called after the subscriber calls 'complete'. No more values can be returned */
done();
}
});

See the examples in the docs: https://rxjs-dev.firebaseapp.com/guide/observable

Return an empty Observable from an Angular2 Service

Replace Observable.empty() with Observable.of([]). The perference of of over empty is what the official Angular Tour of Heroes tutorial uses to return an empty observable, and is what I have been using in all my apps.

The difference between them seems to be whether nothing is returned, or an empty array.

From the official rxjs docs:

Observable.empty()

Creates an Observable that emits no items to the Observer and immediately emits a complete notification.

Observable.of()

Creates an Observable that emits some values you specify as arguments, immediately one after the other, and then emits a complete notification.

map and filter on observable return empty result

not sure about your observable and when you expect it to emit, but a possiblility is because you are using a Subject that only will emit when you do a .next. can you try switching it to a BehaviorSubject, that will emit whenever something subscribes to it. (although I don't know why adding a .pipe() would change that)

Why doesn't EMPTY complete the observable?

Try to use the third callback:

this.claimStoreService.setProducts(this.claim.products)
.pipe(switchMap(x => {
if (this.incomeEligibility) {
return this.claimStoreService.saveIncomeEligibility();
} else {
return EMPTY;
}
}))
.subscribe(
() => this.goIntoDisplayMode(),
console.err,
() => this.isSaving = false,
);

RxJS Type signature of EMPTY observable?

I think you can try Observable<never>, got the idea from EMPTY's implementation

export const EMPTY = new Observable<never>(subscriber => subscriber.complete());


Related Topics



Leave a reply



Submit