RXJS - Ловить исключение, выданное наблюдателем - PullRequest
0 голосов
/ 02 июня 2018

Я новичок в rxjs и борюсь с обработкой исключений.

Принимая следующий код

let sub = new Subject();

let observer1:Observer<String> =  {
    next : v => {
        console.log("next1-" + v);
        if(v==='fail') {
            throw new Error("fail1");
        }
    },
    error : e => console.error("error1-" + e),
    complete : () => console.log("complete1")
};
sub.subscribe(observer1);

try {
    sub.next("msg1");
    sub.next("msg2");
    sub.next("fail");
    sub.next("msg3");
} catch(e) {
    console.log("Caught:" + e);
}

console.log("That's all");

Я понимаю, что после исключения субъект в основном мертв, а msg3 никогда его не делает.

Похоже, я не могу понять, как перехватить исключение, выброшенное в следующем методе Обозревателя.

Вывод, который я получаю,

> next1-msg1 next1-msg2 next1-fail That's all
> /Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/util/hostReportError.js:9
>     setTimeout(function () { throw err; });
>                              ^
> 
> Error: fail1
>     at Object.next (/Users/peter/playground/rxjsstuff/dist/rxjs1.js:97:19)
>     at SafeSubscriber.__tryOrUnsub (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:263:16)
>     at SafeSubscriber.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:201:22)
>     at Subscriber._next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:139:26)
>     at Subscriber.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:103:18)
>     at Subject.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subject.js:63:25)
>     at Object.<anonymous> (/Users/peter/playground/rxjsstuff/dist/rxjs1.js:107:9)
>     at Module._compile (internal/modules/cjs/loader.js:678:30)
>     at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
>     at Module.load (internal/modules/cjs/loader.js:589:32)

Я предполагаю,Я упускаю что-то фундаментальное здесь, но я не могу найти что.

Я полагаю, что вопрос высокого уровня - как бороться с ошибками / исключениями, возникающими в следующем методе Обозревателя, когда Субъект вызывает следующий?

Все советы приветствуются!

Tx

Питер

1 Ответ

0 голосов
/ 02 июня 2018

Короткий ответ: вы не можете и не должны.Откуда наблюдаемый источник узнает, какие ошибки могут выдавать его наблюдатели?

Длинный ответ заключается в том, что обработка ошибок в RxJS изменилась - в лучшую сторону - в версии 6.

Если вы посмотрите на реализацию next в Subject, вы увидите, что нет обработки ошибок:

next(value?: T) {
  if (this.closed) {
    throw new ObjectUnsubscribedError();
  }
  if (!this.isStopped) {
    const { observers } = this;
    const len = observers.length;
    const copy = observers.slice();
    for (let i = 0; i < len; i++) {
      copy[i].next(value);
    }
  }
}

Субъект просто проходит через своих наблюдателей и next на каждом.

Однако каждый наблюдатель заключен в Subscriber.Если вы посмотрите на источник для subscribe, то увидите, что Subscriber создается путем передачи наблюдателя toSubscriber.

В частности, созданному подписчику.SafeSubscriber.И вот где обработка ошибок:

Если вы посмотрите на next в SafeSubscriber, вы увидите, что __tryOrUnsub называется:

next(value?: T): void {
  if (!this.isStopped && this._next) {
    const { _parentSubscriber } = this;
    if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
      this.__tryOrUnsub(this._next, value);
    } else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) {
      this.unsubscribe();
    }
  }
}

__tryOrUnsub попытается вызвать наблюдателя next, и если произойдет ошибка, он отменит подписку наблюдателя от источника.

Любая ошибка, обнаруженная __tryOrUnsub, будет сообщена с использованием hostReportError - который выдает ошибку асинхронно, чтобы стек вызовов не был размотан.Это сделано для того, чтобы ошибки, возникающие в одном наблюдателе, не влияли на других наблюдателей.

Если вы добавите второго наблюдателя - который не выбрасывает - в ваш пример, вы должны увидеть, что второй наблюдатель ведет себя так же, как выЯ ожидал и получил "msg3".

Бен Леш объяснил эти изменения - и причины, по которым они были сделаны - в недавней презентации .Вы можете проверить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...