我正在使用 redux-saga。我想调度一个动作并在之后立即使用该动作的结果。但是 saga 是异步调度的,之后结果不可用。
class A extends Component{
handleEvent = (e) =>{
this.props.getInfo(param);
//Use Result(this.props.Info) from the action
}
render(){
}
}
function mapStateToProps(state) {
return {
Info : state.infoReducer.info
};
}
function mapDispatchToProps(dispatch) {
return {
getInfo : (val)=>{dispatch(getInfo(val))}
}
}
export default connect(mapStateToProps, mapDispatchToProps) (A);
我的动作创建者:
export function getInfo(data){
return{
type : actionType.GET_INFO,
payload : data
}
}
Saga 函数:
function* getInfo(action){
try {
const response = yield call(post,Endpoint,param,header);
const data = yield response.data;
if(error) yield put({type: GET_INFO_FAIL});
else yield put({ type: GET_INFO_SUCCESS, data });
} catch (e) {
//
}
}
减速器:
const INITIAL_STATE ={
info : ""
}
const infoReducer=(state = INITIAL_STATE, action) => {
switch (action.type) {
case actionType.GET_INFO_SUCCESS:
return{
info : action.data
}
default:
return state;
}
}
答案 0 :(得分:0)
您可以使用承诺创建动作创建者。将 resolve
和 reject
函数作为元传递给动作创建者。然后在 API 调用完成后在 worker saga 中调用 resolve
和 reject
。
我们可以创建 bindActionToPromise
辅助函数来做到这一点。
const bindActionToPromise = (dispatch, actionCreator) => (payload) => {
return new Promise((resolve, reject) => dispatch(actionCreator(payload, { resolve, reject })));
};
function mapDispatchToProps(dispatch) {
return {
getInfo: bindActionToPromise(dispatch, getInfo)
}
}
getInfo
工人传奇:
function* getInfoSaga(action) {
console.log(action);
const {
meta: { resolve, reject },
} = action;
const response = yield call(apiCall);
if (response.error) {
yield put({ type: actionType.GET_INFO_FAIL });
yield call(reject, response.error);
} else {
yield put({ type: actionType.GET_INFO_SUCCESS, data: response.data });
yield call(resolve, response.data);
}
}
然后,您可以像这样立即获得 API 响应:
this.props.getInfo(param).then(res => console.log(res))
一个完整的工作示例:
import { call, put, takeLatest } from 'redux-saga/effects';
import { createStoreWithSaga } from '../../utils';
const actionType = { GET_INFO: 'GET_INFO', GET_INFO_FAIL: 'GET_INFO_FAIL', GET_INFO_SUCCESS: 'GET_INFO_SUCCESS' };
export function getInfo(payload, meta) {
return {
type: actionType.GET_INFO,
payload,
meta,
};
}
function apiCall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ data: 'Info from API', error: null });
// resolve({ data: null, error: new Error('business error') });
}, 1000);
});
}
function* getInfoSaga(action) {
console.log(action);
const {
meta: { resolve, reject },
} = action;
const response = yield call(apiCall);
if (response.error) {
yield put({ type: actionType.GET_INFO_FAIL });
yield call(reject, response.error);
} else {
yield put({ type: actionType.GET_INFO_SUCCESS, data: response.data });
yield call(resolve, response.data);
}
}
function* watchSaga() {
yield takeLatest(actionType.GET_INFO, getInfoSaga);
}
const INITIAL_STATE = {
info: '',
};
const infoReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case actionType.GET_INFO_SUCCESS:
return {
info: action.data,
};
default:
return state;
}
};
const store = createStoreWithSaga(watchSaga, infoReducer);
export const bindActionToPromise = (dispatch, actionCreator) => (payload) => {
return new Promise((resolve, reject) => dispatch(actionCreator(payload, { resolve, reject })));
};
const boundGetInfo = bindActionToPromise(store.dispatch, getInfo);
boundGetInfo({ id: 1 })
.then((res) => {
console.log('res immediately: ', res);
})
.catch((err) => {
console.log('error immediately: ', err);
});
store.subscribe(() => {
console.log('state: ', store.getState());
});
执行输出:
{
type: 'GET_INFO',
payload: { id: 1 },
meta: { resolve: [Function (anonymous)], reject: [Function (anonymous)] }
}
state: { info: 'Info from API' }
res immediately: Info from API