Как сохранить переменную для последующего использования в подписке после завершения mergeMap - PullRequest
1 голос
/ 27 сентября 2019

Я довольно новичок в rxjs и у меня возникают проблемы с поиском правильного ответа на эту проблему в документах и ​​stackOverflow.Любая помощь в том, как правильно структурировать этот код, будет принята с благодарностью.

У меня есть довольно типичное приложение Angular, которое извлекает данные из серверной части для нескольких элементов, выбранных пользователем.Для каждого выбранного элемента сервер должен просмотреть некоторые данные в s3, объединить файлы и отправить результат tar.gz в виде строки в кодировке base64.

Этот результат затем сохраняется во внешнем интерфейсе.

Все это работает хорошо, но я бы хотел иметь возможность "сохранить" параметр id перед вызовом API и использовать его позже в методе subscribe при записи реальных данных.Смотрите код ниже

Спасибо!

Я мог бы использовать concatAll, но я бы хотел остаться с mergeMap по соображениям производительности ...


// i set up the observable from the items that a user has selected
// each item has an id property

function fetch(): void {

  let itemId;

  from(this.selection.selected)
      .pipe(
        take(this.selection.selected.length),
        tap((item) => itemId = item.id),
        mergeMap((item: ItemType): any => {
          return this.fetchMoreDataForItem(item);
        })
      )
      .subscribe((apiResponse: any) => {
        const blob = this.decodeBlob(apiResponse);

        /* would love to somehow retain the itemId of the fetched
           item here, but of course using 'itemId' from the 'tap'
           call will not work as the mergeMap has already moved
           on to the next API call before the subscription is 
           triggered... */

        this.saveBlobToFile(blob, <WOULD LOVE TO HAVE ITEM ID HERE>);

      },
      (err) => console.error(`Error fetching ${err.stack}`),
      () => {
        console.log('Completed download');
      });

}

Ответы [ 3 ]

0 голосов
/ 27 сентября 2019

Я думаю, что нашел способ решить эту проблему ...

То, что я сейчас делаю, использует concatAll() вот так:

function fetch(): void {

  const itemIds = [];

  from(this.selection.selected)
      .pipe(
        take(this.selection.selected.length),
        tap((item) => itemIds.push(item.id)),
        map(item => this.fetchMoreDataForItem(item)),
        concatAll()
      )
      .subscribe((apiResponse: any) => {

        const [ id ] = itemIds.splice(0, 1);

        const blob = this.decodeBlob(apiResponse);
        this.saveBlobToFile(blob, id);

      },
      (err) => console.error(`Error fetching ${err.stack}`),
      () => {
        console.log('Completed download');
      });

}

Но как уже упоминалось: я новичокна RXJS несколько дней назад, и я уверен, что есть более элегантный способ справиться с этим, поэтому любые идеи приветствуются!

Спасибо

0 голосов
/ 27 сентября 2019

Существует селектор результатов для mergeMap позвольте вам пройти item.id вдоль

https://www.learnrxjs.io/operators/transformation/mergemap.html

   mergeMap((item: ItemType): any => {
          return this.fetchMoreDataForItem(item);
        },apiResponse => [apiResponse,item.id])
0 голосов
/ 27 сентября 2019

Используйте оператор карты, чтобы создать пакет с apiResponse и вашим идентификатором.

function fetch(): void {

  let itemId;

  from(this.selection.selected)
      .pipe(
        take(this.selection.selected.length),
        tap((item) => itemId = item.id),
        mergeMap((item: ItemType): any => {
          return this.fetchMoreDataForItem(item).pipe(
            map(apiResponse => [apiResponse,item.id])
            );
        })
      )
      .subscribe(([apiResponse,id]) => {
        const blob = this.decodeBlob(apiResponse);
        this.saveBlobToFile(blob, id);

      },
      (err) => console.error(`Error fetching ${err.stack}`),
      () => {
        console.log('Completed download');
      });

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...