Причина неопределенного источника подписки rx js - PullRequest
0 голосов
/ 17 февраля 2020

В большом приложении Angular 8 у меня периодически возникает эта ошибка:

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    at subscribeTo (subscribeTo.js:27)
    at subscribeToResult (subscribeToResult.js:11)
    at SwitchMapSubscriber._innerSub (switchMap.js:46)
    at SwitchMapSubscriber._next (switchMap.js:36)
    at SwitchMapSubscriber.next (Subscriber.js:49)
    at WithLatestFromSubscriber._next (withLatestFrom.js:57)
    at WithLatestFromSubscriber.next (Subscriber.js:49)
    at WithLatestFromSubscriber._next (withLatestFrom.js:57)
    at WithLatestFromSubscriber.next (Subscriber.js:49)
    at FilterSubscriber._next (filter.js:33)

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

подписка basi c может выглядеть примерно так ...

this.store.pipe(
      select(getAllStatus),
      takeUntil(this.isDestroyed),
      map(loading)
    ).subscribe(isLoading => . . .

, где getAllStatus является импортированным селектор, созданный createSelector. Вышеуказанная ошибка может , а не исходить из такого утверждения, потому что, хотя isLoading может определенно быть undefined, сам наблюдаемый источник - выход канала - никогда не может быть неопределенным.

Итак, мы получим более интересный случай. (Обратите внимание, это просто случайный пример из моей кодовой базы; это , а не строка, вызывающая ошибку.)

ngOnInit() {
  this.authorizedChecker.isAuthorized$.subscribe(. . .
}

Успех подписки зависит от того, когда authorizedChecker и его свойство isAuthorized$ оба инициализированы. Поскольку ошибка жалуется на попытку подписки, это означает, что authorizedChecker определенно определено. Но если его isAuthorized$ еще не определено, это может вызвать данную ошибку.

Теперь в конструкторе определено authorizedChecker. В данном конкретном случае это явное создание объекта ...

constructor(
    private store: Store<NgrxStateAtom>
  ) {
    this.authorizedChecker = new AuthorizedChecker(this.store);
  }

, но существуют другие применения, где он создается путем внедрения зависимости, например:

constructor(
    public layoutFacade: LayoutFacadeService
  ) {

В любом случае , мы знаем, что конструктор подкомпонентов завершит свою работу до получения объекта; конструктор AuthorizedChecker начинается с этого ...

constructor(private store: Store<NgrxStateAtom>) {
    this.isAuthorized$ =
      this.store.select(allPerms).pipe(. . .

Поскольку в конструкторе определено isAuthorized$, то вызов, с которого я начал (this.authorizedChecker.isAuthorized$.subscribe), должен никогда завершиться с ошибкой данная ошибка.

Но это заставило меня задуматься: а что если isAuthorized$ определено в ngOnInit? Документы по крюкам жизненного цикла не очень go в деталях. Как подкомпоненты ngOnInit относятся к текущему компоненту ngOnInit, где предпринимается попытка subscribe? Кажется, нет никакой гарантии заказа, так что это может вызвать ошибку. (Похоже, это небезопасная практика - определять Observables в ngOnInit; так ли это?)

Вариант этого - в области шаблона, где можно использовать выражение типа {{ isAuthorized$ | async }}). Я не нашел подробностей о том, как канал asyn c создает свою неявную подписку, но, по-видимому, подвержен тем же обстоятельствам и, следовательно, может быть источником ошибки.

Вопросы: Я смотрю в правильном направлении? ? Существуют ли другие сценарии ios, которые могут вызвать эту ошибку?

...