Return an empty Observable
Asked Answered
V

15

267

The function more() is supposed to return an Observable from a get request

export class Collection {
  public more = (): Observable<Response> => {
    if (this.hasMore()) {
      return this.fetch();
    } else {
      // return empty observable
    }
  };

  private fetch = (): Observable<Response> => {
    return this.http.get("some-url").map((res) => {
      return res.json();
    });
  };
}

In this case I can only do a request if hasMore() is true, else I get an error on subscribe() function subscribe is not defined, how can I return an empty Observable?

this.collection.more().subscribe(
  (res) => {
    console.log(res);
  }, (err) => {
    console.log(err);
  }
);
Vancevancleave answered 24/7, 2016 at 3:17 Comment(0)
V
34

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

In RXJS >= 6

import { EMPTY } from 'rxjs'
return EMPTY;
Vancevancleave answered 23/12, 2021 at 17:13 Comment(0)
B
201

With the new syntax of RxJS 5.5+, this becomes as the following:

// RxJS 6
import { EMPTY, empty, of } from "rxjs";

// rxjs 5.5+ (<6)
import { empty } from "rxjs/observable/empty";
import { of } from "rxjs/observable/of";

empty(); // deprecated use EMPTY
EMPTY;
of({});

Just one thing to keep in mind, EMPTY completes the observable, so it won't trigger next in your stream, but only completes. So if you have, for instance, tap, they might not get trigger as you wish (see an example below).

Whereas of({}) creates an Observable and emits next with a value of {} and then it completes the Observable.

E.g.:

EMPTY.pipe(
    tap(() => console.warn("i will not reach here, as i am complete"))
).subscribe();

of({}).pipe(
    tap(() => console.warn("i will reach here and complete"))
).subscribe();
Beggarweed answered 1/12, 2017 at 20:5 Comment(6)
You can also just do of() I believeAmpersand
of('foo') does emit and complete the observable immediately. rxviz.com/v/0oqMVW1oEscalate
@Escalate yes you are correct, my bad for using take(1) removed for a better answer. @MatthijsWessels, yes and no, just tested this now and if you do of() will return a complete observable without emitting nextBeggarweed
empty is now deprecated, use EMPTY instead (used as a constant instead of as a method, see answer by Simon_Weaver).Supersaturate
Please bear in mind, of() does not emit any value. If you want one, you should provide any value, even undefined or null is ok for that: of(null) emits the value (and processes with tap/subscribe methods), while of() does not.Elinaelinor
Be wary of EMPTYs relationship with .subscribe(). For example, EMPTY.subscribe(() => {console.log('test');}) probably doesn't do what you think it does. More info here blog.novanet.no/rxjs-getting-fooled-by-empty-observablesMorganstein
G
151

For typescript you can specify generic param of your empty observable like this:

import 'rxjs/add/observable/empty' 

Observable.empty<Response>();
Graz answered 19/8, 2016 at 6:24 Comment(1)
This should now be import "EmptyObservable" from "rxjs/observable/EmptyObservable";, then new EmptyObservable<Response>();.Favourable
H
63

RxJS6 (without compatibility package installed)

There's now an EMPTY constant and an empty function.

  import { Observable, empty, EMPTY, of } from 'rxjs';

  //This is now deprecated
  var delay = empty().pipe(delay(1000));     
  var delay2 = EMPTY.pipe(delay(1000));

Observable.empty() doesn't exist anymore.

Hoarsen answered 5/5, 2018 at 19:17 Comment(5)
Update guide: github.com/ReactiveX/rxjs/blob/master/MIGRATION.mdHoarsen
If you have a conflict such as an empty() function already you can say import { empty as rxEmpty } or import { empty as _empty } and then do rxEmpty() or _empty(). Of course that's a pretty non standard thing to do and I'm not actually recommending it, but I'm sure I'm not the only one that was surprised RxJS thinks it is worthy of importing functions like of and empty into my namespace!Hoarsen
careful if using Angular because there's also import { EMPTY } from "@angular/core/src/render3/definition"; which is completely not what you want. So if you're getting odd errors make sure you're not importing that by mistake.Hoarsen
Observable.empty() actually still exists but it's deprecated in favor of EMPTY.Lint
Be wary of EMPTYs relationship with .subscribe(). For example, EMPTY.subscribe(() => {console.log('test');}) probably doesn't do what you think it does. More info here blog.novanet.no/rxjs-getting-fooled-by-empty-observablesMorganstein
I
51

Several ways to create an Empty Observable:

They just differ on how you are going to use it further (what events it will emit after: next, complete or do nothing) e.g.:

  • Observable.never() - emits no events and never ends.
  • Observable.empty() - emits only complete.
  • Observable.of({}) - emits both next and complete (Empty object literal passed as an example).

Use it on your exact needs)

Isoleucine answered 29/6, 2018 at 12:23 Comment(0)
H
42

In my case with Angular2 and rxjs, it worked with:

import {EmptyObservable} from 'rxjs/observable/EmptyObservable';
...
return new EmptyObservable();
...
Highlander answered 9/10, 2016 at 8:56 Comment(2)
include it with import {EmptyObservable} from 'rxjs/observable/EmptyObservable';Unstick
getting error like this, DO I need to configure anything in system-config ? Unhandled Promise rejection: (SystemJS) XHR error (404 Not Found) loading localhost:9190/node_modules/rxjs/Observable/EmptyObservable.js Error: XHR error (404 Not Found) loading localhost:9190/node_modules/rxjs/Observable/EmptyObservable.jsPuton
V
34

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

In RXJS >= 6

import { EMPTY } from 'rxjs'
return EMPTY;
Vancevancleave answered 23/12, 2021 at 17:13 Comment(0)
E
29

Yes, there is am Empty operator

Rx.Observable.empty();

For typescript, you can use from:

Rx.Observable<Response>.from([])
Err answered 24/7, 2016 at 3:55 Comment(6)
I'm getting Rx.Observable<{}> is not assignable to Observable<Response>, I tried to Rx.Observable<Response>.empty() but it didn't workVancevancleave
I changed the return type to Observable<any> and it worked, thanks mate.Vancevancleave
It should be Rx.Observable.from([]) without <Response>. Otherwise getting an error "expression expected".Sealer
You can also use Rx.Observable.of([]).Sealer
@AndriyTolstoy I am not sure this is equivalent. In Observable.of([]), there is one value emitted ( []) and then the stream completes. With Observable.from([]), no value is emitted, the stream completes immediately.Sterigma
The documentation states that it's better to use the import {EMPTY} from 'rxjs' (better than the empty() method). I assume that it's a memory thing (i.e. reusing the same empty values is better than creating multiple empty objects)Thermogenesis
R
19

You can return Observable.of(empty_variable), for example

Observable.of('');

// or
Observable.of({});

// etc
Reisch answered 24/7, 2016 at 3:57 Comment(0)
E
5

Differents way to return empty observable :

  1. Observable.from({});
  2. Observable.of({});
  3. EMPTY

https://www.learnrxjs.io/learn-rxjs/operators/creation/empty

Eleventh answered 23/12, 2021 at 19:58 Comment(0)
N
2

Or you can try ignoreElements() as well

Nochur answered 24/7, 2016 at 11:7 Comment(0)
F
2

RxJS 6

you can use also from function like below:

return from<string>([""]);

after import:

import {from} from 'rxjs';
Falls answered 13/5, 2018 at 16:14 Comment(1)
This will create an Observable that will provide one element (an empty string), so it doesn't look like a proper answer to this specific question.Andryc
D
2

Came here with a similar question, the above didn't work for me in: "rxjs": "^6.0.0", in order to generate an observable that emits no data I needed to do:

import {Observable,empty} from 'rxjs';
class ActivatedRouteStub {
  params: Observable<any> = empty();
}
Drucie answered 23/8, 2018 at 19:31 Comment(0)
M
0

Try this

export class Collection{
public more (): Observable<Response> {
   if (this.hasMore()) {
     return this.fetch();
   }
   else{
     return this.returnEmpty(); 
   }            
  }
public returnEmpty(): any {
    let subscription = source.subscribe(
      function (x) {
       console.log('Next: %s', x);
    },
    function (err) {
       console.log('Error: %s', err);
    },
    function () {
       console.log('Completed');
    });
    }
  }
let source = Observable.empty();
Migdaliamigeon answered 24/7, 2016 at 4:16 Comment(0)
G
0

You can return the empty observable with all different ways but challenge is to to return it with the expected type - Here is the way to create a empty observable with type -

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
return next.handle(this.setHeaders(req))
            .pipe(
                catchError((error: HttpErrorResponse) => {
        // you write your logic and return empty response if required
        return new Observable<HttpEvent<any>>();
            }));
    }
Geoffrey answered 23/12, 2021 at 6:42 Comment(0)
M
0

there is another: EMPTY const

Replaced with the EMPTY constant or scheduled (e.g. scheduled([], scheduler)). Will be removed in v8. (got this form phpstorm hint)

Mile answered 31/8, 2022 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.