Есть ли лучший способ последовательного вызова разнородных наблюдаемых вызовов? - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть два метода API:

  • POST / article / {id} / revisions
  • GET / article / {id}

Результатом публикации ревизий является документ ревизии, который включает в себя изменения до / после объекта статьи.Это не объект статьи.

Они соответствуют следующим методам в моем приложении Angular:

  • this.endpoint.articles.revise(article.id, revisionParams);
  • this.endpoint.articles.getById(article.id);

Которые возвращают Observable<ArticleRevision> и Observable<Article> соответственно.

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

private reviseArticle(article: article, revisionParams: ArticleRevisionParams): Observable<Article> {
    return this.endpoint.articles.revise(article.id, revisionParams)
        .expand(r => this.endpoint.articles.getById(article.id))
        .pipe(take(2))
        .last();
}

Из описания или expand, похоже, что этот метод больше взломать, чемРешение:

Рекурсивный вызов предоставленной функции.

Я пытался использовать concat, но обнаружил, что для этого требуются наблюдаемые того же типа, что было немногопокажи стопор в моем случае.Неправильно ли я использую expand, или есть лучший (более правильный) способ последовательного связывания разнородных наблюдаемых?

PS Я пометил Angular в случае, если связанный с Angular ароматизатор rxjs немного отличается от обычногоrxjs.Не стесняйтесь удалить его, если он не принадлежит.

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Чтобы выполнить это без типа контейнера, вы можете воспользоваться оператором forkJoin.

Идея состоит в том, чтобы составить промежуточный результат так, чтобы он состоял из результатаот вашего первого запроса, а также от вашего второго запроса, который зависит от вашего первого запроса.Часть этой композиции потребует от вас превратить первый результат запроса в наблюдаемую, что вы можете сделать с помощью of.

Впоследствии вы можете деструктурировать ответы на каждый запрос отодин результирующий аргумент массива (т.е. ([reviseResult, getByIdResult]) => { ... }).

const { forkJoin, of } = rxjs;
const { switchMap } = rxjs.operators;

function revise(id, params) {
  return of({ id, params, operation: 'revise' });
}

function getById(id) {
  return of({ id, operation: 'getById' });
}

revise(1).pipe(
  switchMap(reviseResult => forkJoin(of(reviseResult), getById(reviseResult.id))),  
).subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
0 голосов
/ 13 февраля 2019

Кстати, я считаю, что Angular использует ту же библиотеку rxjs, что и остальные из нас, основываясь на этом package.json .

К счастью, rxjs предлагает несколько вариантов завершениязадачи по-разному.Лично я не использовал расширение таким образом, но это выглядит как довольно аккуратная реализация.

Один из способов сделать это - создать новый интерфейс для хранения обоих типов:

export interface MyTypes {
  rev: ArticleRevision;
  article: Article;
}

Таким образом, вы можете вернуть один тип из вашего потока, используя оператор switchMap и задав значение обоих ответов для одного типа и возвращая наблюдаемый.

Черновик:

export interface MyTypes {
  rev: ArticleRevision;
  article: Article;
}
private reviseArticle(article: article, revisionParams: ArticleRevisionParams): Observable<MyTypes> =>
  this.endpoint.articles.revise(article.id, revisionParams)
    .pipe(
      switchMap((rev: ArticleRevision) =>
        this.endpoint.articles.getById(article.id)
          .pipe(
            switchMap((art: Article) => ({
              rev: rev,
              article: art,
            })
          )
    );

Вы также можете использовать switchMap для возврата массива двух значений в качестве наблюдаемого (аналогично приведенному выше, просто вернуть их в массив).

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