我在我的项目中使用了redux-saga。 之前我使用过redux-thunk,所以我无法设置某些异步请求的StateState。像
this.props.thunkAsync()
.then(){
this.setState({ '' });
}
由于thunk返回promise,我可以使用'then'。 但我无法用传奇做到这一点,因为传奇并没有回报承诺。 所以我在componentWillReceiveProps中通过检查标志道具(如REQUEST_SUCCESS,REQUEST_WAITING ......)来改变它。 我认为这不是解决这个问题的好方法。
那么..我的问题是当异步请求在redux-saga中结束时,我该如何做一些工作!
答案 0 :(得分:4)
但是我无法用传奇做到这一点,因为传奇并没有回报承诺
Redux-saga
与thunk
略有不同,因为它是流程管理器,而不是简单的中间件:thunk
仅对已触发的操作执行反应,但saga
有自己的&# 34;处理" (正式回调刻度域)并且可以通过效果操作。
使用redux-saga
执行异步操作的常用方法是将原始操作拆分为ACTION_REQUEST
,ACTION_SUCCESS
和ACTION_FAILURE
变体。然后reducer只接受SUCCESS / FAILURE动作,也许接受optimistic updates的REQUEST。
在这种情况下,您的saga
流程可能如下
function* actionNameSaga(action) {
try {
const info = yield call(fetch, { params: action.params }
yield put('ACTION_NAME_SUCCESS', info)
} catch(err) {
yield put('ACTION_NAME_FAILURE', err)
}
function* rootSaga() {
yield takeEvery('ACTION_NAME', actionNameSaga)
}
请记住,yield
操作本身不是关于承诺等待 - 它只是委托等待saga进程管理器的异步。
答案 1 :(得分:2)
您进行的每个api调用都将作为异步请求处理,但会使用传奇中的生成器函数进行处理。
因此,在成功调用api之后,您可以执行以下可能的操作。
function* onLogin(action) { try { const { userName, password } = action; const response = yield call(LoginService.login, userName, password); yield put(LoginService.loginSuccess(response.user.id)); const branchDetails = yield call(ProfileService.fetchBranchDetails, response.user.user_type_id); yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails)); } catch (error) { yield put(ProfileActions.fetchUserDetailsError(error)); } }
API成功后传递回叫
onLoginClick() {
const { userName, password } = this.state;
this.props.login(userName, password, this.onLoginSuccess);
}
onLoginSuccess(userDetails) {
this.setState({ userDetails });
}
function *onLogin(action) {
try {
const { userName, password, onLoginSuccess } = action;
const response = yield call(LoginService.login, userName, password);
if (onLoginSuccess) {
onLoginSuccess(response);
}
yield put(LoginService.loginSuccess(response.user.id));
const branchDetails = yield call(ProfileService.fetchBranchDetails,
response.user.user_type_id);
yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails));
} catch (error) {
yield put(ProfileActions.fetchUserDetailsError(error));
}
}
更新Reducer状态并通过mapStateToProps从道具获取
yield put(LoginService.loginSuccess(response.user.id));
@connect(
state => ({
usedDetails: state.user.get('usedDetails'),
})
)
static getDerivedStateFromProps(nextProps, prevState) {
const { usedDetails } = nextProps;
return {
usedDetails
}
}
答案 2 :(得分:0)
您可以这样做。在组件属性中,您可以调用saga方法,并在成功或失败后传递要执行的功能,如下所示
export function* login({ payload }) {
const url = 'localhost://login.json';
try {
const response = yield call(App_Service, { url, method: 'GET' });
if (response.result === 'ok' && response.data.body) {
yield put(fetchDataActionCreators.getLoginSuccess(response.data.body));
//function passed as param from component, pass true if success
payload.callback(true);
}
} catch (e) {
//function passed as param from component, pass false if failure
payload.callback(false);
console.log(e);
}
}
export function* watchLogin() {
while (true) {
const action = yield take(LOGIN);
yield* login(action);
}
}
export default function* () {
yield all([
fork(watchLogin)
]);
}
在函数中的组件调用调用setState方法中,以参数形式传递给saga
login() {
// store
this.props.getServiceDetails({
callback:(success) => this.onLoginSuccess(success)
})
}
onLoginSuccess = (success) => {
this.setState({
login:success
})
alert('login '+success)
}
答案 3 :(得分:0)
我也遇到了同样的问题...
我的解决方案是将调度包裹在一个Promise中,并在saga函数中调用resolve和拒绝...
我创建了一个用于包装分发的钩子。您可以在这里看到我的示例: https://github.com/ricardocanelas/redux-saga-promise-example
我希望可以对某人有所帮助。