如何在RxJS中基于第一个响应发出多个Ajax请求

如何在RxJS中基于第一个响应发出多个Ajax请求,rxjs,redux-observable,Rxjs,Redux Observable,我正在使用redux observable epic,使用搜索端点从GitHub上的特定组织获取回购。我的主要问题是我需要按“观察者”进行排序,所以我需要所有的回购协议,但GitHub只允许每页最多返回100个。响应包括“total_count”,我可以用它来计算我还需要发出多少请求(共页)。以下是我目前的代码: export const fetchRepos = actions$ => actions$.pipe( ofType(FETCH_REPOS), switc

我正在使用redux observable epic,使用搜索端点从GitHub上的特定组织获取回购。我的主要问题是我需要按“观察者”进行排序,所以我需要所有的回购协议,但GitHub只允许每页最多返回100个。响应包括“total_count”,我可以用它来计算我还需要发出多少请求(共页)。以下是我目前的代码:

export const fetchRepos = actions$ =>
  actions$.pipe(
    ofType(FETCH_REPOS),
    switchMap(action =>
      ajax.getJSON(`https://api.github.com/search/repositories?q=org:${action.payload.orgName}&per_page=100`).pipe(
        flatMap((response) => ([setRepos(response.items), setCurrentOrg(action.payload.orgName), fetchReposSuccess(response.item)])),
        catchError(error => of(fetchReposFailed()))
      )   
    )   
  ); 

我想知道如何使用“总数”支持第一个响应,根据该数字发出更多ajax请求并合并到一个流中,而不需要对代码进行太多更改。

我认为最简单的方法是使用操作符递归地从ajax调用中投影响应,您可以决定是否需要抓取更多页面。因此,您甚至不需要使用
total_count
,因为您只需继续下载页面,直到获得的项目少于
每页的项目数
参数:

例如,我可以从我的帐户中获取所有存储库:

const PER_PAGE = 10;
const API_URL = 'https://api.github.com/search/repositories';

const makeAjax = page => ajax.getJSON(`${API_URL}?q=org:martinsik&per_page=${PER_PAGE}&page=${page}`).pipe(
  map(response => ([page, response])),
);

makeAjax(1)
  .pipe(
    expand(([page, response]) => response.items.length < PER_PAGE
      ? empty()
      : makeAjax(page + 1)
    ),
    map(([page, response]) => response),
    toArray(),
  )
  .subscribe(console.log);
const PER_PAGE=10;
const API_URL='1〕https://api.github.com/search/repositories';
const makeAjax=page=>ajax.getJSON(`${API\u URL}?q=org:martinsik&per\u page=${per\u page}&page=${page}').pipe(
映射(响应=>([第页,响应]),
);
makeAjax(1)
.烟斗(
展开(([page,response])=>response.items.length<每页
?空()
:makeAjax(第+1页)
),
映射([页面,响应]=>响应),
toArray(),
)
.subscribe(console.log);

观看现场演示:

非常酷,谢谢!当我查看演示的网络选项卡时,我注意到每个URL有2个请求。一种类型为“fetch”,另一种类型为“xhr”。你能解释一下吗?其中一个总是一些服务人员的响应,我不知道stackblitz对它们做了什么,可能它们只是被缓存了。在调用我的其他操作之前,有没有办法将所有项目放入一个平面数组?toArray()不太适合我。您可以使用
scan(…)收集所有响应。takeLast(1)