Javascript 并行多个ajax调用并在成功后调度redux操作将导致;未捕获错误:操作必须是普通对象;

Javascript 并行多个ajax调用并在成功后调度redux操作将导致;未捕获错误:操作必须是普通对象;,javascript,reactjs,redux,rxjs,redux-observable,Javascript,Reactjs,Redux,Rxjs,Redux Observable,我是rxjs和redux observable的新手。尝试创建一个epic,允许我执行多个并行ajax调用,并在成功时分派相应的操作: const loadPosters = (action$) => action$.pipe( ofType(Types.LOAD_FILMS_SUCCESS), switchMap(({ films }) => forkJoin(films.map(film => ajax .getJSON(`https

我是rxjs和redux observable的新手。尝试创建一个epic,允许我执行多个并行ajax调用,并在成功时分派相应的操作:

const loadPosters = (action$) => action$.pipe(
  ofType(Types.LOAD_FILMS_SUCCESS),
  switchMap(({ films }) =>
    forkJoin(films.map(film =>
      ajax
      .getJSON(`https://api.themoviedb.org/3/search/movie?query=${film.title}`)
      .pipe(
        map(response => {
          const [result] = response.results;
          const poster = `http://image.tmdb.org/t/p/w500/${result.poster_path}`;
          return Creators.savePoster(film, poster);
        })
      ),
    ))
  ),
);
Creators.savePoster()
是名为
SAVE\u POSTER
的动作的动作创建者。但是,每当我运行应用程序时,都不会调度这样的操作。相反,我在浏览器控制台中收到一条错误消息:

未捕获错误:操作必须是普通对象。使用自定义中间件 用于异步操作

编辑 尝试了一个没有
forkJoin
的简化版本,遗憾的是得到了相同的结果:

const loadPosters = (action$) => action$.pipe(
  ofType(Types.INIT_SUCCESS),
  mergeMap(({ films }) =>
    films.map(film =>
      ajax
      .getJSON(`https://api.themoviedb.org/3/search/movie?query=${film.title}`)
      .pipe(
        map(response => {
          const [result] = response.results;
          const poster = `http://image.tmdb.org/t/p/w500/${result.poster_path}`;
          console.log(Creators.savePoster(film, poster));
          return Creators.savePoster(film, poster);
        })
      )
    ),
  ),
);
附录 仅供参考,我还有另一个epic,它执行一个简单的ajax调用,效果很好:

const loadFilms = action$ => action$.pipe(
  ofType(Types.INIT_REQUEST),
  mergeMap(() =>
    ajax
    .getJSON('https://star-wars-api.herokuapp.com/films')
    .pipe(
      map(response => Creators.initSuccess(response))
    ),
  ),
);

问题是我没有在我的内部映射中返回一个可观察的。更改:

return Creators.savePoster(film, poster);

让它工作

顺便说一下,如果与
forkJoin
一起使用,也可以(在我的情况下更好)在解决所有请求后获取映射结果,并发送单个操作,而不是多个操作:

const loadPosters = (action$) => action$.pipe(
  ofType(Types.INIT_SUCCESS),
  mergeMap(({ films }) =>
    forkJoin(
      films.map(film =>
        ajax
        .getJSON(`https://api.themoviedb.org/3/search/movie?query=${film.title}`)
        .pipe(
          map(response => ({ film, response }))
        )
      ),
    )
  ),
  mergeMap(data => {
    const posters = data.reduce((acc, { film, response}) => ({
      ...acc,
      [film.id]: `http://image.tmdb.org/t/p/w500/${response.results[0].poster_path}`,
    }), {});
    return of(Creators.savePosters(posters));
  })
);

事实上,到目前为止,这是我最喜欢的解决方案。

这很好,正是我想要的:)但是我对失败的ajax调用有一个问题,您知道如何为每个成功调用分配成功操作,并为失败的ajax响应分配有效响应和失败操作吗?我甚至试过联合测试,但没有成功!可能有线索吗?谢谢
const loadPosters = (action$) => action$.pipe(
  ofType(Types.INIT_SUCCESS),
  mergeMap(({ films }) =>
    forkJoin(
      films.map(film =>
        ajax
        .getJSON(`https://api.themoviedb.org/3/search/movie?query=${film.title}`)
        .pipe(
          map(response => ({ film, response }))
        )
      ),
    )
  ),
  mergeMap(data => {
    const posters = data.reduce((acc, { film, response}) => ({
      ...acc,
      [film.id]: `http://image.tmdb.org/t/p/w500/${response.results[0].poster_path}`,
    }), {});
    return of(Creators.savePosters(posters));
  })
);