Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将api调用包装器从redux thunk迁移到redux saga_Javascript_Reactjs_Redux_Redux Thunk_Redux Saga - Fatal编程技术网

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

Javascript 如何将api调用包装器从redux thunk迁移到redux saga,javascript,reactjs,redux,redux-thunk,redux-saga,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(

我最近开始使用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;
    });
};
export const callApi=(promise:promise,errorMsg:string='Api error')=>(dispatch:dispatch)=>{
调度(设置加载(真));
回报你的承诺(
(回应)=>{
调度(设置加载(假));
返回响应.body;
},
(错误)=>{
调度(设置加载(假));
调度(apiError(errorMsg,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));
    };
}
const camelizeKeysPromise=(obj)=>Promise.resolve(camelizeKeys(obj));
导出函数*sagacalapi(promise:promise,errorMsg:string='Api error'){
屈服put(设定载荷(真));
试一试{
常量响应=收益调用(承诺);
试一试{
const result=yield调用(camelizeKeysPromise(response.body));
返回结果;
}捕获(e){
返回响应.body;
}
}捕获(例外){
屈服put(设置加载(假));
产量投入(APIRROR(errorMsg,error));
};
}

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

const promiseEmitter = promise => {
  return eventChannel(emit => {
    promise.then(
      response => emit({response}),
      error => emit({error})
    );
  });
};
修改您的新传奇,用以下内容取代对承诺的呼唤:

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));
}

请注意,当我在没有编辑器的情况下编写本文时,我的代码中可能存在语法错误,但您可以使用一般方法

谢谢你的回答。我刚刚在频道上读了些东西。如果我传递了一个函数返回一个承诺,而不是一个承诺,那么就不需要这样做了。你可能会遇到同样的问题,因为如果你对该函数产生调用效果,你将得到承诺而不是响应,除非我不理解你的问题。