如何将api调用包装器从redux thunk迁移到redux saga

时间:2017-01-17 16:15:50

标签: javascript reactjs redux redux-thunk redux-saga

我最近开始使用redux-saga,我真的很喜欢它。

我有以下包装器,我用于api调用,它会接受一个承诺(我的api调用),并显示预加载器并处理错误。

export const callApi = (promise: Promise<any>, errorMsg: string = 'Api error') => (dispatch: Dispatch) => {
  dispatch(setLoading(true));
  return promise.then(
    (response) => {
      dispatch(setLoading(false));
      return response.body;
    },
    (error) => {
      dispatch(setLoading(false));
      dispatch(apiError(errorMsg, error));
      return error;
    });
};

我不确定如何在redux传奇中复制这样的行为。我找不到做这样的事情的例子吗?

到目前为止,我已经提出了

const camelizeKeysPromise = (obj) => Promise.resolve(camelizeKeys(obj));


export function* sagaCallApi(promise: Promise<any>, errorMsg: string = 'Api error') {
   yield put(setLoading(true));
   try {
      const response = yield call(promise);
      try {
        const result = yield call(camelizeKeysPromise(response.body));
        return result;
      } catch (e) {
        return response.body;
      }
   } catch (exception) {
      yield put(setLoading(false));
      yield put(apiError(errorMsg, error));
    };
}

1 个答案:

答案 0 :(得分:1)

产生call承诺将不会返回所需的回复。您可以使用eventChannel中的redux-saga创建一个成功响应的通道或失败时的错误对象,然后订阅您的传奇中的频道。

const promiseEmitter = promise => {
  return eventChannel(emit => {
    promise.then(
      response => emit({response}),
      error => emit({error})
    );
  });
};

通过用以下方法替换对promise的调用来修改你的新传奇:

const channel = yield call(promiseEmitter, promise);
const {response, error} = yield take(channel);
if(response){
  // handle success
  return response;
}else if(error){
  // handle failure
  yield put(setLoading(false));
  yield put(apiError(errorMsg, error));
}

请注意我的代码中可能存在语法错误,因为我在没有编辑器的情况下编写了这个错误,但您可以获得一般方法。