2017-01-23 1 views
1

У меня есть ситуация, я не знаю, как обращаться. Ситуация заключается в том, чтобы долго вытащить Firebase, получить некоторые данные как наблюдаемые обратно к ngrx/effects, а затем снова вызвать Firebase, чтобы удалить некоторые данные, а затем, наконец, передать первые данные о возврате Firebase в Action для редуктора, чтобы выполнить свою задачу.Стратегии связывания операций RXJS в ngrx/эффектах для вызова Firebase для различных операций до вызова действия

Вот код ngrx/эффекты

constructor(private threadsService: ThreadsService, private store: Store<ApplicationState>) { 

     } 

     @Effect() newMessages$ = Observable.interval(5000) 
     .withLatestFrom(this.store.select("uiState")) 
     .map(([any,uiState]) => uiState) 
     .do(console.log) 
     .filter(uiState => uiState.userId) 
     .switchMap(uiState => this.threadsService.loadNewMessagesForUser(uiState.userId)) 
     .withLatestFrom(this.store.select("uiState")) 
     .do(console.log) 
     .switchMap(([messages, uiState]) => this.threadsService.deleteMessagesQueuePerUser(messages, uiState.userId)) 
     .map(messages => new NewMessagesReceivedAction(messages)) 

Первый this.threadsService.loadNewMessagesForUser (uiState.userId) получит Firebase данные я в конце концов нужно для NewMessagesReceivedAction (сообщений). Но перед тем, как я передаю сообщение видимым, мне также нужно удалить MessageQueuePerUser, чтобы следующий интервал возвращался пустым, поскольку новое сообщение уже было вытащено. Но приведенный выше код не будет работать, и имеет обалденный результат и много ошибок:

ОШИБКА # 1: без .Не (console.log) перед фильтром, этот код

.filter(uiState => uiState.userId) 

выдаст ошибку в WebStorm - Свойство 'идентификатор пользователя' не существует на типа '{}')

ERROR # 2: эти 3 строки просто не будет работать:

// .withLatestFrom(this.store.select("uiState")) 
// .do(console.log) 
// .switchMap(([messages, uiState]) => this.threadsService.deleteMessagesQueuePerUser(messages, uiState.userId)) 

идея этих 3 линий продолжать. передать сообщение наблюдаемым вниз, но мне также нужно, чтобы uiState.userId удалял некоторые данные в Firebase, используя это: this.threadsService.deleteMessagesQueuePerUser (сообщения, uiState.userId). Но наблюдаемые сообщения в первом списке Firebase не опускаются во второй. Вот код threadsService:

firebaseUpdate(dataToSave) { 

    const subject = new Subject(); 

    this.sdkDb.update(dataToSave) 
     .then(
     val => { 
      subject.next(val); 
      subject.complete(); 
     }, 
     err => { 
      subject.error(err); 
      subject.complete(); 
     } 
    ); 

    return subject.asObservable(); 
    } 

    loadNewMessagesForUser(uid: string): Observable<Message[]> { 

    console.log ("We are pulling the server! uid: " + uid); 

    return this.findMessagesForMessageKeys(this.findMessageKeysPreUserUnread(uid)); 

    } 

    findMessagesForMessageKeys(messageKeys$:Observable<string[]>): Observable<Message[]> { 
return messageKeys$ 
    .map(pspp => pspp.map(messageKey => this.db.object('message/' + messageKey))) 
    .flatMap(fbojs => Observable.combineLatest(fbojs)) 
    } 

    deleteMessagesQueuePerUser(messages:Observable<Message[]>, uid:string): Observable<Message[]> { 

    let dataToSave = {}; 
    dataToSave['MessagesQueuePerUser/' + uid] = null; 
    this.firebaseUpdate(dataToSave); 
    return messages; 
    } 

    findMessageKeysPreUserUnread(uid: string):Observable<string[]> { 
    return this.db.list('MessagesQueuePerUser/' + uid) 
     .map(getKeys => getKeys.map(p => p.$key)); 
    } 

Может кто-нибудь мне точку в правильном направлении, чтобы выяснить, как структурировать и писать это право?

ОБНОВЛЕНИЕ для уточнения.

Да У меня есть тип UiState. И я действительно хочу получить NewMessages из this.threadsService.loadNewMessagesForUser (uiState.userId). ПОСЛЕ того, как я получаю NewMessages (так как это наблюдаемая операция async), я хочу запустить действие delete (более похоже на побочный эффект внутри побочного эффекта). Когда я запускаю действие NewMessagesReceivedAction (сообщения), данные должны быть из этого.threadsService.loadNewMessagesForUser (uiState.userId). Надеюсь, это немного изменит ситуацию.

ответ

2

Я предполагаю, что у вас есть тип UiState.

Это один из способов сделать это:

@Effect() newMessages$ = Observable.interval(5000) 
    .withLatestFrom(this.store.select("uiState"))   
    .map(([any,uiState]) => uiState) 
    .filter(uiState => uiState.userId) 
    .switchMap(uiState => threadsService.loadNewMessagesForUser(uiState.userId) 
     .switchMap(newMessages => threadsService.deleteMessagesQueuePerUser(newMessages, uiState.userId) 
     .map(deletedMessages => newMessages))) 
    .map(messages => ({ type:'MESSAGES_RECEIVED', payload: messages })); 

Работа plunker: https://embed.plnkr.co/BdZOD3XHEXU14GveQUBv/

+0

Hi @John Hamm. Спасибо за ответ. Я обновил свой вопрос, чтобы прояснить ситуацию. Надеюсь, что это поможет. Идеальная ситуация: мне НЕ нужно передавать сообщения в this.threadsService.deleteMessagesQueuePerUser, поэтому я могу упростить эту функцию как this.threadsService.deleteMessagesQueuePerUser (userId). Я просто не знаю, как получить NewMessage от наблюдаемого ПЕРЕД. Кроме того, ваше решение, я получаю userId? Вы отображаете только сообщения, откуда приходит userId, поскольку он принадлежит коммутатору. –

+0

Ваше решение, есть ошибка машинописного текста: аргумент типа 'Message []' не присваивается параметру типа 'Observable '. Это ошибка подсветки сообщений в this.threadsService.deleteMessagesQueuePerUser (messages, userId) –

+0

Вы получаете userId из содержащего switchMap. Вы заметите, что внутренний «.map (messages ...» будет иметь доступ к любым переменным, переданным на любые внешние карты или наблюдаемые. Вместо того, чтобы заканчивать switchMap после загрузкиNewMessagesForUser, я просто перекодирую другую карту на первую карту, а не заканчивая switchMap, чтобы он мог получить доступ к userId. –

Смежные вопросы