Skip to content

include setTimeout in EventEmitter onError and onComplete #4443

@PatrickJS

Description

@PatrickJS

summary

EventEmitter should also resolve onError and onComplete asynchronously for both onError and onComplete.

problem

On the server, I'm running into a problem EventEmitter because onComplete is called before onNext

export class EventEmitter extends Observable {
  _subject = new Subject();

  observer(generator: any): any {
    return this._subject.subscribe((value) => { setTimeout(() => generator.next(value)); },
                                   (error) => generator.throw ? generator.throw(error) : null,
                                   () => generator.return ? generator.return () : null);
  }

  toRx(): any { return this; }

  next(value: any) { this._subject.next(value); }

  throw(error: any) { this._subject.error(error); }

  return (value?: any) { this._subject.complete(); }

should be

export class EventEmitter extends Observable {
  _subject = new Subject();

  observer(generator: any): any {
    return this._subject.subscribe((value) => { setTimeout(() => generator.next(value)); },
                                   (error) => generator.throw ? setTimeout(() => generator.throw(error)) : null,
                                   () => generator.return ? setTimeout(() => generator.return()) : null);
  }

  toRx(): any { return this; }

  next(value: any) { this._subject.next(value); }

  throw(error: any) { this._subject.error(error); }

  return (value?: any) { this._subject.complete(); }
}

current workaround

include setTimeout for onError and onComplete

background/why

as far as I know, setTimeout was added in order for zone.js to pick up any changes. The problem is that onComplete resolves first without this change since onNext is push to the event loop. If you have any dispose logic in the onComplete callback then whatever obj you're working with may not work during the onNext callback. For example

ObservableWrapper
  .subscribe(
    request,
    value => {
      console.log('onnext');
      // obs.next() won't do anything because we ran `obs.return()` which disposes the object
      ObservableWrapper.callNext(obs, value);
    },
    e => {
      console.log('onerror');
      ObservableWrapper.callThrow(obs, e);
    },
    () => {
      console.log('oncomplete');
      ObservableWrapper.callReturn(obs);
    });

If you wrap onError and onComplete callbacks with setTimeout then they work as expected

proposal

find a better way to notify zone.js than setTimeout or include setTimeout in the other callbacks

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions