Обработка ошибок с помощью асинхронной трубки Angular2

Я использую асинхронный канал Angular2 для потока значений в DOM. Вот простой пример:

const stream = Observable.interval(1000)
  .take(5)
  .map(n => { if (n === 3) throw "ERROR"; return n; });

<div *ngFor="for num of stream | async">
  {{num}}
</div>

<div id="error"></div>

Что бы я хотел сделать, так это отобразить последовательность 1-5, но в элементе ошибки (3) каким-то образом заполнить #error div сообщением об ошибке.

Это, по-видимому, требует двух вещей: во-первых, способность асинхронного канала Angular делать что-то интеллектуальное с ошибками, которое я не вижу. Глядя на исходный код, по-видимому, он генерирует исключение JS, которое не выглядит слишком дружелюбным.

Во-вторых, это возможность перезапуска или продолжения последовательности после ошибки. Я читал о catch и onErrorResumeNext и т.д., Но все они связаны с другой последовательностью, на которую будет включена ошибка. Это значительно усложняет логику генерации потока, на котором я хотел бы просто поместить ряд чисел (в этом простом примере). У меня есть ощущение тонуса, что, как только возникает ошибка, игра завершена, и наблюдаемое завершено и может быть только "перезапущено" с другим наблюдаемым. Я все еще изучаю наблюдаемые; это на самом деле случай?

Итак, мой вопрос двоякий:

  • Может ли Angular2 асинхронная труба сделать что-то умное с ошибками?
  • Есть ли у наблюдателей некоторый простой способ продолжить работу после ошибки?

Ответ 1

Да, вы правы в отношении оператора catch и способности что-то делать после ошибок...

Я бы использовал оператор catch, чтобы поймать ошибку и сделать что-то:

const stream = Observable.interval(1000)
  .take(5)
  .map(n => {
    if (n === 3) {
      throw Observable.throw(n);
    }
    return n;
  })
  .catch(err => {
    this.error = error;
    (...)
  });

и в шаблоне:

<div>{{error}}</div>

Чтобы иметь возможность перейти к исходному наблюдаемому, вам нужно создать новый, начиная с того места, где происходит ошибка:

createObservable(i) {
  return Observable.interval(1000)
    .range(i + 1, 5 - i)
    .take(5 - i)
  });
}

и использовать его в обратном вызове catch:

  .catch(err => {
    this.error = error;
    return this.createObservable(err);
  });

Эти два вопроса могут помочь вам:

Ответ 2

1) no, труба async подписывает и отменяет подписку и возвращает полученные события. Вам нужно будет обрабатывать ошибки, прежде чем они получат трубку async.

2) Вы можете использовать оператор catch и когда он возвращает наблюдаемый, тогда его значение (и) испускается вместо .catch(err => Observable.of(-1)) вместо ошибки.

Вы можете использовать это, чтобы испустить специальное значение "ошибка", а затем использовать что-то вроде *ngIf="num === -1, чтобы показать значение ошибки каким-то особым образом.

Вы можете найти дополнительную информацию об этом https://blog.thoughtram.io/angular/2017/02/27/three-things-you-didnt-know-about-the-async-pipe.html