TypeError: You provided an invalid object where a stream was expected

TypeError: You provided an invalid object where a stream was expected

以下代码有效。它执行一个 ajax 请求,然后一次调用 2 个操作:

export const loadThingsEpic = action$ => {

  return action$.ofType(LOAD_THINGS)
    .mergeMap(({things}) => {
      const requestURL = `${AppConfig.serverUrl()}/data/things`;
      return ajax.getJSON(requestURL)).map(response => {
        return finishLoadingThings(response);
      }).map(() => {
        return sendNotification('success');
      });
    })
    .catch(e => {
      return concat(of(finishLoadingThings({ things: {} })),
                    of(sendNotification('error')));

    });   
}}

但是这段代码没有:

export const loadThingsEpic = action$ => {

  return action$.ofType(LOAD_THINGS)
    .mergeMap(({things}) => {
      const requestURL = `${AppConfig.serverUrl()}/data/things`;
      return ajax.getJSON(requestURL).switchMap(response => {
        return concat(of(finishLoadingThings(response)),
                      of(sendNotification('success')));
      });
    })
    .catch(e => {
      return concat(of(finishLoadingThings({ things: {} })),
                    of(sendNotification('error')));
    });   
}

我已将地图替换为 switchMap 以将 2 个动作合并在一起(如许多其他 post 所示)。如果抛出异常,它会在 catch 中起作用。我想知道代码有什么问题。我猜这是因为我似乎无法真正掌握何时使用:map、swicthMap 和 mergeMap。

sendNotification 和 finishLoadingthings returns 操作对象:

export function finishLoadingThings(data: any) {
  return {
    type: FINISH_LOADING_THINGS,
    data,
  };
}

谢谢!

按原样提供的代码似乎按预期工作:https://jsbin.com/becapin/edit?js,console当 ajax 成功或失败时,我没有收到 "invalid object where stream expected" 错误。

您确定错误来自此代码吗?


另外,您可能会很高兴听到 Observable.of 支持任意数量的参数,每个参数都会一个接一个地发出。所以不是这个:

.switchMap(response => {
  return concat(of(finishLoadingThings(response)),
                of(sendNotification('success')));
});

你可以这样做:

.switchMap(response => {
  return of(
    finishLoadingThings(response),
    sendNotification('success')
  );
});

虽然这不会导致错误,但它更干净。

我设法解决了我的问题,方法是在与 mergeMap 相同的级别执行 switchMap。像这样:

export const loadThingsEpic = action$ => {

  return action$.ofType(LOAD_THINGS)
    .mergeMap(({things}) => {
      const requestURL = `${AppConfig.serverUrl()}/data/things`;
      return ajax.getJSON(requestURL).switchMap(response => {
        return of(response);
      });
    })
    .switchMap((res) => {
       return concat(of(finishLoadingThings(res.value)),
                      of(sendNotification('success')));
    })
    .catch(e => {
      return concat(of(finishLoadingThings({ things: {} })),
                    of(sendNotification('error')));
    });   
}

还不太明白。