Screenpunch
Screenpunch

Reputation: 51

Can I used RxJS-DOM over RxJS with Redux-Observable

Redux-Observable has a dependency on RxJS.

I need to use the filereader function from RxJS-DOM.

https://github.com/Reactive-Extensions/RxJS-DOM/blob/master/doc/operators/filereader.md

It looks like RxJS-DOM contains the same basic set of APIs as RxJS (plus the DOM ones).

Is it possible to ask Redux-Observable to use RxJS-DOM rather than RxJS? Importing both is bloating the size of my build.

Upvotes: 2

Views: 321

Answers (1)

jayphelps
jayphelps

Reputation: 15401

RxJS-DOM aka rx-dom is for RxJS v4, not for v5+. The two are incompatible. The situation is confusing, indeed.

In v5+ there is no official equivalent to fromReader, here's the issue ticket tracking: https://github.com/ReactiveX/rxjs/issues/1223

Although probably not what you want to hear, creating custom Observable wrappers around other APIs should be fairly simple as long as you do understand how Observables fundamentally work. It's a pretty valuable skill to learn, regardless.

fromReader is actually a misnomer since you don't provide it a FileReader, you provide it a File and it internally creates its own FileReader to drain it. So let's say fromFile instead. This is a very basic starting point example:

class FromFileAsTextObservable extends Observable {
  constructor(file, encoding) {
    super();

    this.file = file;
    this.encoding = encoding;
  }

  _subscribe(subscriber) {
    const reader = new FileReader();

    const loadHandler = event => {
      subscriber.next(event.target.result);
      subscriber.complete();
    };

    const errorHandler = event => {
      subscriber.error(event.target.error);
    };

    reader.addEventListener('load', loadHandler, false);
    reader.addEventListener('error', errorHandler, false);

    reader.readAsText(this.file, this.encoding);

    return () => {
      reader.removeEventListener('load', loadHandler, false);
      reader.removeEventListener('error', errorHandler, false);
    };
  }
}

class FromFileFactory {
  constructor(file) {
    this.file = file;
  }

  asText(encoding) {
    return new FromFileAsTextObservable(this.file, encoding);
  }
}

const fromFile = file =>
  new FromFileFactory(file);

const file = new File(['hello world'], 'example.txt', {
  type: 'text/plain',
});

fromFile(file).asText()
  .subscribe(text => console.log(text));

While that's the more flexible way for complex APIs and such, if all you want to do is read a file and handle load/error, you could instead create an anonymous Observable like so:

const fromFileAsText = (file, encoding) => new Observable(subscriber => {
  const reader = new FileReader();

  const loadHandler = event => {
    subscriber.next(event.target.result);
    subscriber.complete();
  };

  const errorHandler = event => {
    subscriber.error(event.target.error);
  };

  reader.addEventListener('load', loadHandler, false);
  reader.addEventListener('error', errorHandler, false);

  reader.readAsText(file, encoding);

  return () => {
    reader.removeEventListener('load', loadHandler, false);
    reader.removeEventListener('error', errorHandler, false);
  };
});

const file = new File(['hello world'], 'example.txt', {
  type: 'text/plain',
});

fromFileAsText(file)
  .subscribe(text => console.log(text));

Upvotes: 3

Related Questions