Реализация ggradnig - правильное решение, однако я бы хотел более подробно проанализировать ПОЧЕМУ это работает, чтобы не было путаницы, если кто-нибудь столкнется с этой проблемой в будущем.
Когда вы подписываетесь на наблюдаемое, большую часть времени вы передаете только одну функцию обратного вызова, которая описывает, как вы хотите обрабатывать данные из потока при его получении. В действительности, хотя есть 3 различных обратных вызова, которые могут быть включены в наблюдателя для различных типов событий. Это:
next - Вызывается при получении данных из потока. Так что, если вы делаете запрос на получение статистики покемонов, он собирается
вызвать функцию «следующего» обратного вызова и передать эти данные как
вход. В большинстве случаев это единственные данные, которые вас интересуют, и
Создатели rxjs знали об этом, поэтому, если вы включите только 1 обратный вызов
функция в подписке, подписка будет по умолчанию
передача «следующих» данных в этот обратный вызов.
ошибка - Довольно понятно. Если в вашу наблюдаемую ошибку не попадает ошибка, она вызывает этот обратный вызов.
- complete - Вызывается, когда наблюдаемое завершается.
Если вы хотите иметь дело со всеми различными типами данных, генерируемых наблюдаемой, вы можете написать в своей подписке наблюдателя, который будет выглядеть примерно так:
this.http.get(“https://pokemon.com/stats/bulbasaur”).subscribe({
next: () => { /* deal with pokemon data here */},
error: () => {/* called when there are errors */},
complete: () => {/* called when observable is done */}
})
Опять же, в большинстве случаев это не нужно, но важно понимать эти типы событий, когда мы вызываем метод .toPromise () в Observable. Когда мы конвертируем Observable в Promise, происходит то, что Promise собирается разрешить с последними «следующими» данными, полученными из Observable, как только будет вызван метод «Complete» в Observable. Это означает, что, если «Полный» обратный вызов не вызван, Обещание будет зависать бесконечно.
Да, я знаю, о чем вы думаете: я постоянно преобразую свои http-запросы из Observables в Promises, и я никогда не сталкиваюсь с ситуацией, когда мое Promise зависает бесконечно. Это потому, что угловая http-библиотека вызывает «завершенный» обратный вызов в Observable, как только все данные получены из http-вызова. Это имеет смысл, потому что, как только вы получите все данные из запроса, вы закончите. Вы не ожидаете больше данных в будущем.
Это отличается от ситуации, описанной в вопросе, когда вы звоните в пожарный магазин, и, как я знаю по опыту, для передачи информации используются сокеты, а не запросы http. Это означает, что через соединение вы можете получить начальный набор данных ... и затем больше данных ... и затем больше данных. По сути, это поток, который не имеет определенного конца, поэтому у него никогда нет причин вызывать «полный» обратный вызов. То же самое произойдет с предметами Поведение и Повтор.
Чтобы обойти эту проблему, вы должны заставить Observable вызвать обратный вызов «Complete», либо добавив «first ()» или «take (1)», что будет делать то же самое, вызовите функцию обратного вызова «next» с исходным набором данных в качестве входных данных, а затем вызовите обратный вызов «Complete».
Надеюсь, это кому-нибудь пригодится, потому что эта проблема запутала меня до чертиков.
Также это видео является отличным справочником, если вы все еще не уверены: https://www.youtube.com/watch?v=Tux1nhBPl_w