Итак, я пытался понять это в течение 2 дней, и я сдался, rxjs очень сложен, особенно когда речь идет о семействе map
.
У меня есть действие MessageRequested
с параметром id
, которое должно инициировать вызов API для получения сообщения, а затем проверить, находится ли соответствующий посетитель в магазине или нет. Если его нет в магазине, он отправит два действия, MessageLoaded
и VisitorRequested
. Если он находится в магазине, мы просто отправим одно действие MessageLoaded
. Таким образом, логика будет в следующем порядке:
MessageRequested
было отправлено с id
в качестве входа - Теперь мы вызываем API с
id
в качестве параметра, мывернул Message
объект. Определение сообщения ниже. Он имеет свойство visitor_id
: mergeMap((action) => this.converseService.getMessage( action[0].message_id ))
- Теперь мы запрашиваем у магазина, существует ли
visitor_id
в Message
объекте в состоянии посетителя (this.store.pipe(select(selectVisitorById( m.visitor_id ) )
) Теперь у нас есть условие if, которое мы должны применить,
a. если select
что-то вернул, то посетитель уже находится в магазине, и мы вернем только действие MessageLoaded
.
b. Если select
не вернул visitor
, теперь мы должны отправить дополнительное действие VisitorRequested
, чтобы запросить посетителя. Нам все еще нужно отправить действие MessageLoaded
. Так вот 2 действия.
Теперь к коду:
loadMessage$ = this.actions$
.pipe(
ofType<MessageRequested>(MessageActionTypes.MessageRequested),
mergeMap((action) => this.converseService.getMessage( action[0].message_id )),
map(m => m.model),
withLatestFrom( this.store.pipe(select(selectVisitorById( m.visitor_id ) ))),
tap( ([message,visitor]) => {
if (visitor == null) new VisitorRequested(message.visitor_id);
}),
map( ([message, visitor]) => {
return new MessageLoaded({message});
} )
);
export class Message {
id: number;
message: string;
visitor_id: number;
is_from_visitor: boolean;
created_at: string;
}
export class MessageResponse extends Response {
model: Message
}
export class Response{
message:String;
didError: boolean;
errorMessage: string;
}
Код выглядит хорошо, за исключением того, что withLatestFrom
не принимает входные данные, поэтому яне могу передать переменную m.visitor_id
, и теперь мне нужно подумать о другом подходе. Я пытался использовать forkJoin
и concatMap
, но не сделал этого.
Какие правильные операторы использовать в сценарии?
Обновление # 1
Эточто в итоге сработало с помощью всех ответов:
@Effect()
loadMessage$ = this.actions$
.pipe(
ofType<MessageRequested>(MessageActionTypes.MessageRequested),
mergeMap((action) => this.converseService.getMessage( action.message_id )),
map(m => m.model),
concatMap(message =>
of(message).pipe(
withLatestFrom(this.store.pipe(select(selectVisitorById(message.visitor_id))))
)
),
tap( ([message,visitor]) => {
if (!(visitor)) this.store.dispatch(new VisitorRequested(message.visitor_id));
}),
map( ([message, visitor]) => {
return new MessageLoaded({message});
} )
);