В большом приложении 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, которые могут вызвать эту ошибку?