如何将 api 调用包装器从 redux thunk 迁移到 redux saga
How to migrate api call wrapper from a redux thunk to 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 saga 中复制这样的行为。我找不到任何这样的例子吗?
到目前为止我想出了
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));
};
}
做出 call
承诺不会 return 想要的回应。您可以使用 redux-saga
中的 eventChannel
创建一个频道,该频道在成功时发出响应或在失败时发出错误对象,然后订阅您的传奇中的频道。
const promiseEmitter = promise => {
return eventChannel(emit => {
promise.then(
response => emit({response}),
error => emit({error})
);
});
};
修改您的新 saga,将对 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));
}
请注意,我在没有使用编辑器的情况下编写此代码时可能存在语法错误,但您可以获得一般方法。
我最近开始使用 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 saga 中复制这样的行为。我找不到任何这样的例子吗?
到目前为止我想出了
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));
};
}
做出 call
承诺不会 return 想要的回应。您可以使用 redux-saga
中的 eventChannel
创建一个频道,该频道在成功时发出响应或在失败时发出错误对象,然后订阅您的传奇中的频道。
const promiseEmitter = promise => {
return eventChannel(emit => {
promise.then(
response => emit({response}),
error => emit({error})
);
});
};
修改您的新 saga,将对 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));
}
请注意,我在没有使用编辑器的情况下编写此代码时可能存在语法错误,但您可以获得一般方法。