Ответ 1
Как рассуждать о наблюдаемых?
Наблюдаемые сделки с потоками. Потоки могут быть практически любыми, но вы можете думать о них как о абстрактном массиве асинхронных событий. Это полезно, потому что теперь вы можете более четко рассуждать о них:
- abstract, поскольку Observable может генерировать значение любого типа:
String, Boolean, Object
- массив, поскольку Observable имеет
Operators
, который работает аналогично методам массива JavaScript:map(), filter(), reduce()
- из, потому что Observable - это оболочка для значений (-ов)
- асинхронный, поскольку Observable может выполнять или не выполнять
- события, потому что Observable должен быть запущен
Когда использовать Observables?
Вы хотите использовать Observables, как правило, когда вам нужно выполнить задачу или действие, которое включает в себя несколько шагов. Это может быть вашей отправной точкой, вы можете позже упростить или увеличить сложность по мере необходимости.
У вас должен быть "план" или, по крайней мере, смутное представление о том, какими должны быть эти шаги. Звучит очевидно, но многие проблемы/проблемы возникают из-за того, что вы не знаете, что хотите (;
Как только вы планируете действие (как массив шагов), вы можете начать с любого конца, но я думаю, что лучше начать с конца. По крайней мере, пока вы не узнаете больше.
У меня есть компонент, который просто отображает список сообщений для общей темы. Пока у меня есть одна тема, к которой относятся все сообщения. Если тема не существует, то она должна быть создана. Вызов сообщения и темы все делается через REST api.
В неасинхронном мире я запрограммировал его по порядку. Служба сообщений увидит, существует ли тема. Если это не так, то это создает сервис тем. После того, как у него есть тема, он извлекает все сообщения в этом разделе.
В вашем случае использования План будет выглядеть следующим образом: ["(create topic)", "select topic", "show messages"]
. messages
абстрактный массив, select
и create
являются асинхронными событиями.
Как использовать наблюдаемый?
Как я сказал выше, пусть начнется с конца - "show messages"
.
<div *ngFor="#message of messages"></div>
Мы знаем, что имеем дело с Observable.of(messages)
(так вы его вручную создадите). Затем вам нужно "заполнить" поток сообщений, и вы можете сделать это с помощью службы Http
, которая возвращает Observable
. Поскольку сообщения, которые вы получаете с сервера, обернуты несколькими "слоями" службой Http
, мы можем использовать способность Observable для операторов цепочек (операторы возвращать Observable
) и получать сообщения, которые нам нужны:
getMessages(topic) {
this.http.get("/messages?topic=" + topic)
.map(response => response.json())
// chain other operators here...
.filter(message => !message.private)
}
Вы можете использовать любые Operators, которые вам нужны здесь..., что приводит к следующей большой заметке об Observables:
"Горячие" и "Холодные" наблюдения
По умолчанию наблюдаемые холодные. Это означает, что когда вы создаете наблюдаемый, вы просто описываете, что он должен делать. Он не будет выполнять эти действия немедленно (например, Promises
do), он должен быть запущен.
Вы запускаете его, подписываясь на него, либо вручную с помощью метода subscribe()
, либо вы можете позволить Angular сделать его горячим с помощью async
pipe (который подписывается для вас).
getMessages(topic) {
this.http.get("/messages?topic=" + topic)
.map(response => response.json())
.subscribe(messages => this.messages = messages);
}
Наблюдение за изменениями
Следующее, что нужно сделать (или ранее, когда мы возвращаемся в План), находится в "select topic"
. Было бы неплохо посмотреть значение выбранной темы и отреагировать на нее, изменив загрузку новых сообщений. Это можно сделать с помощью Subject
.
Объект - это своего рода мост или прокси, доступный в некоторых реализациях ReactiveX, который действует как наблюдатель, так и как наблюдаемый. Поскольку он является наблюдателем, он может подписаться на один или несколько Observables, и поскольку он является наблюдаемым, он может проходить через элементы, которые он наблюдает, повторно их удаляя, и он также может генерировать новые элементы.
Мы можем настроить topic$
следующим образом:
class ListComponent {
public messages;
public topic$ = new Subject();
constructor(private http: Http) {
this.getMessages('posts');
this.topic$
.subscribe(topic => this.getMessages(topic));
}
getMessages(topic: string) {....}
selectTopic(topic: string) {
this.topic$.next(topic)
}
}
Обернуть
Последний шаг - "(create topic)"
, если его не существует. Пусть предположим, что сервер вернет ошибку, если тема не существует:
getMessages(topic: string) {
this.http.get(API_URL + topic)
.map(response => response.json())
.subscribe(
messages => this.messages = messages,
error => this.createTopic(topic)
);
}
createTopic(topic: string) {
this.http.post(API_URL + topic, { body: JSON.stringify(topic) })
.map(response => response.json())
.subscribe();
}
Здесь рабочий плункер с этим примером. Как вы можете видеть, это непросто сделать (50-и строчные строки кода...). Вы можете легко перемещать вещи и создавать сервисы там, где вам нужно.