我有一个传奇(使用redux-saga
)调用一个POST到API端点的函数(使用axios
)。通过axios进行更深入的API调用会返回一个承诺。我想在承诺的then()
方法中发送操作,但我显然不能使用yield
。 put()
似乎没有放任何东西。什么是正确的方法?
这是传奇:
export function* loginFlow(action) {
try {
const {username, password} = action.payload;
const responsePromise = yield call(login, {username, password, isRegistering: false});
yield responsePromise
.then(result => {
console.log('loginFlow responsePromise result', result);
put(creators.queueLoginSucceededAction()); // doesn't work
put(push('/')); // doesn't work
})
.catch(err => {
console.log('loginFlow responsePromise err', err);
put(creators.queueLoginFailedAction()); // doesn't work
});
}
catch(err) {
console.log(err);
yield put(creators.queueLoginFailedAction());
}
}
这是被调用的函数:
export function* login(options) {
try {
// if we are already logged in, via token in local storage,
// then skip checking against server
if( store.get('token') ) {
return Promise.resolve('Already logged in.');
}
// query server for valid login, returns a JWT token to store
const hash = yield bcrypt.hashSync(options.password, 10);
yield put(creators.queueLoginHttpPostedAction());
return axios.post('/auth/local', {
params: {
username: options.username,
password: hash,
hash: true,
}
})
.then(result => {
console.log('api>auth>login>result', result);
put(creators.queueLoginHttpSucceededAction()); // doesn't work
return Promise.resolve('Login successful');
})
.catch(err => {
console.log('api>auth>login>err', err);
put(creators.queueLoginHttpFailedAction()); // doesn't work
return Promise.reject(err.message);
});
}
catch (err) {
yield put(creators.queueLoginHttpFailedAction());
return Promise.reject('Login could not execute');
}
}
答案 0 :(得分:1)
一个传奇的收益电话'将等待返回的承诺完成。如果失败,则会抛出错误,因此不使用'然后'并且'赶上'对于承诺,你可以使用普通的try-catch。
Redux Saga文档更详细地解释了这一点 - 绝对值得一读:
https://redux-saga.js.org/docs/basics/ErrorHandling.html
换句话说,下面的login(options)
函数将执行HTTP请求,只要它不发回被拒绝的承诺,它就会继续对成功的操作进行排队并将用户重定向回来。如果它确实发回了被拒绝的承诺,它将立即跳转到' catch'而是阻止。
更正了登录流程:
export function * loginFlow(action) {
try {
const {username, password} = action.payload;
const responsePromise = yield call(login, {username, password, isRegistering: false});
console.log('loginFlow responsePromise result', result);
yield put(creators.queueLoginSucceededAction());
yield put(push('/'));
}
catch(err) {
console.log('loginFlow responsePromise err', err);
yield put(creators.queueLoginFailedAction());
}
}
对于实际的登录过程:
export function * login(options) {
// if we are already logged in, via token in local storage,
// then skip checking against server
if( store.get('token') ) {
return Promise.resolve('Already logged in.');
}
// query server for valid login, returns a JWT token to store
const hash = yield bcrypt.hashSync(options.password, 10);
yield put(creators.queueLoginHttpPostedAction());
try {
yield call(
axios.post,
'/auth/local',
{ params: { username: options.username, password: hash, hash: true } }
)
console.log('api>auth>login>result', result);
yield put(creators.queueLoginHttpSucceededAction()); // doesn't work
return Promise.resolve('Login successful');
} catch(err) {
console.log('api>auth>login>err', err);
yield put(creators.queueLoginHttpFailedAction()); // doesn't work
return Promise.reject(err.message);
}
}