首页 > 解决方案 > 如何使用 RxJS 发出多个 HTTP 请求并将响应合并到一个有效负载中并将其映射到另一个动作?

问题描述

根据标题,我一直在尝试找出一种方法来从动作有效负载进行多个 HTTP 调用,基本上将所有结果合并到一个数组中,然后将结果作为有效负载映射到另一个动作。

这是我现有的代码,它可以工作,但似乎没有合并两个响应,只关心请求响应的最后一个响应,也许我使用了错误的运算符,我只是拿起 RxJS 并尝试不同的东西来学习,希望有人能够解释我要去哪里错了。

非常感谢任何帮助或指导。


{
    type: 'FETCH_DATA',
    payload: {
        key: 'standings',
        value: [
                'http://url-1',
                'http://url-2'
        ],
    })
}


// The epic is listening to the above action

const fetchDataEpic = action$ => action$.pipe(
    ofType('FETCH_DATA'),
    mergeMap(action => {
        const { key, value } = action.payload;
        if (Array.isArray(value) && value.length) {
            const makeRequest = value.map((x, i) => ajax.getJSON(value[i]))

            return (
                forkJoin(
                    makeRequest,
                    response => {
                        return ({
                            type: 'FETCH_DATA_SUCCEEDED',
                            payload: {
                                key,
                                value: response,
                            },
                        })
                    }
                )
            )
        }
    })
);

注意:两个请求的响应都是相同的 JSON 格式,具有相同的属性,但数据不同。

提前致谢

标签: javascriptreactjsrxjsobservablerxjs6

解决方案


看起来您正在使用 rxjs 的 ajax 函数,它应该已经为您提供了 observables。在这种情况下,一旦所有可观察对象都发出了值,forkJoin 应该将这两个值作为数组提供。然后您可以使用 map 函数将其添加到您的操作负载中。

const requestArrays = [1, 2].map(i => {
  return rxjs.ajax.ajax.getJSON(`https://jsonplaceholder.typicode.com/posts/${i}`);
});

rxjs.forkJoin(requestArrays)
  .pipe(
    rxjs.operators.tap(resp => {
      console.log('Part 1: Response so far: ');
      console.log(resp);
    }),
    rxjs.operators.map(value => {
      return {
        type: 'FETCH_DATA_SUCCEEDED',
        payload: {
          value
        }
      };
    }),
    rxjs.operators.tap(resp => {
      console.log('Part 2: Result as a action payload: ');
      console.log(resp);
    }),
  )
  .subscribe();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>


编辑:这大致是你将如何实现它。

const action = {
  type: 'FETCH_DATA',
  payload: {
    value: [
      '1',
      '2'
    ],
  }
};

rxjs.of(action)
.pipe(
    rxjs.operators.mergeMap(action => {
      const requestArrays = action.payload.value.map(i => {
        return rxjs.ajax.ajax.getJSON(`https://jsonplaceholder.typicode.com/posts/${i}`);
      });
      return rxjs.forkJoin(requestArrays)
      .pipe(
          rxjs.operators.map(value => {
            return {type: 'FETCH_DATA_SUCCEEDED', payload: {value}};
          })
      )
    })
)
.subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>


推荐阅读