как создать только одну подписку () этого кода - PullRequest
0 голосов
/ 04 июля 2018

Я сделал этот код, который выполняет свою работу, используя RxJS:

from(dateQuery.first())
  .subscribe((result) => {
      query.greaterThanOrEqualTo('createdAt', result.createdAt);

      const dateFormat = moment(result.createdAt).format('DD/MM/YYYY - HH:mm:ss');
      from(query.find())
        .map(el => el.map((e) => {
          return {
            id: e.id,
            username: e.get('username')
          }
        }))
        .mergeMap((array) => Observable.of({
          names: array,
          lastUpdate: dateFormat
        }))
        .subscribe(
          (next) => res.send(serialize(next)),
          (error) => res.send(serialize(error)),
          () => console.log('completed'));
    },
    (error) => console.log(error)
  );

Мой вопрос: возможно ли создать только одну подписку вместо этих двух? Потому что мне нужно использовать результат первой подписки также в другой mergeMap раньше, и я не знаю, как его сохранить, если я попытаюсь сделать только одну подписку.

Спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Вот моя первая идея из того, что я понял.

Я экспортировал первую подписку в наблюдаемую и повторно использую ее для создания второй наблюдаемой (find$), где я делаю вторую подписку.

Я не знаю, что делает query.greaterThanOrEqualTo('createdAt', result.createdAt), поэтому я положил это в оператор .do() в качестве побочного эффекта. Если вам необходимо выполнить этот метод перед выполнением оставшегося кода, верните наблюдаемую информацию или обещание из нее, а также используйте mergeMap.

    const dataQueryFirst$ = dateQuery.first();
    const find$ = dataQueryFirst$
        .do((result) => query.greaterThanOrEqualTo('createdAt', result.createdAt))
        .mergeMap(result => {
           const dateFormat = moment(result.createdAt).format('DD/MM/YYYY - HH:mm:ss');
           return from(query.find())
               .map(el => el.map((e) => {
                   return {
                       id: e.id,
                       username: e.get('username')
                }}))
               .mergeMap((array) => Observable.of({
                   names: array,
                   lastUpdate: dateFormat
               }))
           });
    find$.subscribe(
        (next) => res.send(serialize(next)),
        (error) => res.send(serialize(error)),
        () => console.log('completed')
    );
0 голосов
/ 04 июля 2018

Я бы реализовал это с помощью SwitchMap. Плюс я бы извлек некоторую логику в функции, чтобы сделать его более читабельным. И я предпочитаю новый "pipe" способ rxjs начиная с v5.5.

from(dateQuery.first()).pipe(
    // TAP because it seems to be a sideeffect. If this could stop your stream, "filter" would be appropriate
    tap(result =>query.greaterThanOrEqualTo('createdAt', result.createdAt)),
    // MAP because we can discard "result" and only need the Moment-Object in the rest of the stream
    map(result => getMoment(result.createdAt),
    // switchMap to switch to the second stream, because it is only one command (in a long pipe) you don´t need a explicit return-command
    switchMap( createdAt => 
        from(query.find()).pipe(
            // MAP because we now want a UserObjects-Array in our stream
            map(el => createUserObjects(el)),
            // MAP because we want our NamesUpdateList. Depending on the usage you may not need "Observable.of()" here
            map(userObjects => createNamesUpdateList(userObjects, createdAt ))
        )
    )
).subscribe(
  (next) => res.send(serialize(next)),
  (error) => res.send(serialize(error)),
  () => console.log('completed')
)

getMoment(date){
    return moment(result.createdAt).format('DD/MM/YYYY - HH:mm:ss')
}

createUserObjects(el){
    el.map((e) => {
        return {
            id: e.id,
            username: e.get('username')
        }
    }
}

createNamesUpdateList(array, dateFormat){
    return {
        names: array,
        lastUpdate: dateFormat
    }
}

С уважением

0 голосов
/ 04 июля 2018

Вы можете сделать что-то подобное

from(dateQuery.first()).pipe(
  tap(() => query.greaterThanOrEqualTo('createdAt', result.createdAt)),
  map(result => moment(result.createdAt).format('DD/MM/YYYY - HH:mm:ss')),
  mergeMap(dateFormat => from(query.find()).pipe(
    map(el => el.map((e) => ({
      id: e.id,
      username: e.get('username')
    }))),
    mergeMap((array) => Observable.of({
      names: array,
      lastUpdate: dateFormat
    })),
    tap(() => res.send(serialize(next))),
    catchError(error => of('Find error'))
  ))
).subscribe();
...