263

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);
  }
);
Liam
  • 27,717
  • 28
  • 128
  • 190
Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185

15 Answers15

195

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();
Stephen Lautier
  • 3,065
  • 3
  • 17
  • 20
  • 5
    [You can also just do `of()` I believe](http://reactivex.io/rxjs/test-file/spec-js/observables/of-spec.js.html#lineNumber41) – Matthijs Wessels Jun 28 '18 at 06:42
  • 2
    `of('foo')` does emit and complete the observable immediately. https://rxviz.com/v/0oqMVW1o – SimplGy Jan 31 '19 at 20:42
  • 1
    @SimplGy 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 `next` – Stephen Lautier Feb 04 '19 at 12:30
  • 3
    empty is now deprecated, use EMPTY instead (used as a constant instead of as a method, see answer by Simon_Weaver). – EriF89 Apr 24 '20 at 08:52
  • 5
    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. – Maxím G. May 15 '20 at 22:54
  • Be wary of `EMPTY`s relationship with `.subscribe()`. For example, `EMPTY.subscribe(() => {console.log('test');})` probably doesn't do what you think it does. More info here https://blog.novanet.no/rxjs-getting-fooled-by-empty-observables/ – Liam Aug 23 '21 at 15:04
150

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

import 'rxjs/add/observable/empty' 

Observable.empty<Response>();
Patrick
  • 361
  • 2
  • 12
Andrei Petrov
  • 1,627
  • 1
  • 10
  • 2
  • 33
    This should now be `import "EmptyObservable" from "rxjs/observable/EmptyObservable";`, then `new EmptyObservable();`. –  Apr 17 '18 at 06:39
62

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.

Liam
  • 27,717
  • 28
  • 128
  • 190
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • Update guide: https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md – Simon_Weaver May 05 '18 at 19:18
  • 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! – Simon_Weaver May 25 '18 at 22:15
  • 1
    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. – Simon_Weaver Jan 11 '19 at 09:57
  • 1
    `Observable.empty()` actually [still exists](https://github.com/ReactiveX/rxjs/blob/ffb4b0b52f8f8402ddd354169be285c78fcf9988/src/internal/observable/empty.ts#L62) but it's deprecated in favor of `EMPTY`. – Alexander Abakumov Sep 23 '19 at 14:52
  • Be wary of `EMPTY`s relationship with `.subscribe()`. For example, `EMPTY.subscribe(() => {console.log('test');})` probably doesn't do what you think it does. More info here https://blog.novanet.no/rxjs-getting-fooled-by-empty-observables/ – Liam Aug 23 '21 at 15:05
50

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)

Andrii Verbytskyi
  • 7,155
  • 3
  • 47
  • 38
42

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

import {EmptyObservable} from 'rxjs/observable/EmptyObservable';
...
return new EmptyObservable();
...
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
Marcel Tinner
  • 1,343
  • 11
  • 18
  • 7
    include it with `import {EmptyObservable} from 'rxjs/observable/EmptyObservable';` – Kildareflare Mar 06 '17 at 05:15
  • getting error like this, DO I need to configure anything in system-config ? Unhandled Promise rejection: (SystemJS) XHR error (404 Not Found) loading http://localhost:9190/node_modules/rxjs/Observable/EmptyObservable.js Error: XHR error (404 Not Found) loading http://localhost:9190/node_modules/rxjs/Observable/EmptyObservable.js – user630209 Dec 19 '17 at 06:11
29

Yes, there is am Empty operator

Rx.Observable.empty();

For typescript, you can use from:

Rx.Observable<Response>.from([])
Toan Nguyen
  • 11,263
  • 5
  • 43
  • 59
  • I'm getting `Rx.Observable<{}>` is not assignable to `Observable`, I tried to `Rx.Observable.empty()` but it didn't work – Murhaf Sousli Jul 24 '16 at 04:21
  • I changed the return type to `Observable` and it worked, thanks mate. – Murhaf Sousli Jul 24 '16 at 04:32
  • 2
    It should be `Rx.Observable.from([])` without ``. Otherwise getting an error "expression expected". – Andriy Tolstoy Aug 18 '16 at 12:46
  • 2
    You can also use `Rx.Observable.of([])`. – Andriy Tolstoy Aug 18 '16 at 12:53
  • 1
    @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. – Pac0 Mar 23 '18 at 14:57
  • 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) – bvdb May 23 '19 at 08:40
28

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

In RXJS >= 6

import { EMPTY } from 'rxjs'
return EMPTY;
Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185
19

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

Observable.of('');

// or
Observable.of({});

// etc
Jecfish
  • 4,026
  • 1
  • 18
  • 16
4

Differents way to return empty observable :

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

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

Souhail HARRATI
  • 303
  • 2
  • 7
2

Or you can try ignoreElements() as well

Tuong Le
  • 18,533
  • 11
  • 50
  • 44
2

RxJS 6

you can use also from function like below:

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

after import:

import {from} from 'rxjs';
Nour
  • 5,609
  • 3
  • 21
  • 24
  • 3
    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. – Bruno Medeiros Jun 22 '18 at 02:58
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();
}
Callat
  • 2,928
  • 5
  • 30
  • 47
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();
Jorawar Singh
  • 7,463
  • 4
  • 26
  • 39
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>>();
            }));
    }
viveksharma
  • 557
  • 4
  • 9
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)

Catalin
  • 11
  • 2