redux-saga未抛出异常求助:React Native注册逻辑执行异常
兄弟,我来帮你捋捋这个问题!你遇到的情况是无效邮箱本该触发Firebase的auth/invalid-email错误进入catch分支,但却走到了成功逻辑,修改doRegister后还是不行,大概率是这几个地方出了问题:
1. 先确认doRegister是否正确抛出了错误
很多时候是doRegister内部自己捕获了错误但没重新抛出来,导致Saga的call根本感知不到错误。比如你可能写了这样的代码:
// 错误示例:捕获了错误但没抛出 const doRegister = async (email, password) => { try { const user = await firebase.auth().createUserWithEmailAndPassword(email, password); return user; } catch (err) { console.log('注册错误:', err); // 只打印,没抛出 } };
这种情况下,函数会返回undefined而不是抛出错误,Saga的call就会认为操作成功,自然会执行SIGNUP_SUCCESS。
解决方法:在doRegister的catch块里重新抛出错误:
const doRegister = async (email, password) => { try { const user = await firebase.auth().createUserWithEmailAndPassword(email, password); return user; } catch (err) { console.error('注册错误:', err); throw err; // 关键:把错误抛出去让Saga捕获 } };
2. 检查Saga中try/catch的范围是否正确
如果你的Saga代码里,call(doRegister)不在try块内部,或者成功的put在try块外面,那即使call出错了,也会执行成功逻辑。比如:
// 错误示例:成功逻辑在try/catch外面 function* signupSaga(action) { const { email, password } = action.payload; try { // 这里没放call,白搭 } catch (err) { yield put({ type: 'SIGNUP_FAILURE', payload: err }); } // 不管call成功失败都会执行这里 const user = yield call(doRegister, email, password); yield put({ type: 'SIGNUP_SUCCESS', payload: user }); }
正确写法:把call和成功的put都放在try块里,这样一旦call抛出错误,直接进入catch,不会执行成功逻辑:
function* signupSaga(action) { const { email, password } = action.payload; try { const user = yield call(doRegister, email, password); yield put({ type: 'SIGNUP_SUCCESS', payload: user }); } catch (err) { // 可以在这里判断错误码做针对性处理 if (err.code === 'auth/invalid-email') { console.log('捕获到无效邮箱错误'); } yield put({ type: 'SIGNUP_FAILURE', payload: err }); } }
3. 确认Firebase是否真的抛出了auth/invalid-email错误
有时候你以为的“无效邮箱”,Firebase可能认为是合法的。比如test@test这种没有域名后缀的邮箱,Firebase不会抛出invalid-email,但test@.com这种会。你可以先在doRegister里手动抛出测试错误,验证Saga的catch逻辑是否正常:
const doRegister = async (email, password) => { // 先测试:手动抛出Firebase格式的错误 const testErr = new Error('Invalid email'); testErr.code = 'auth/invalid-email'; throw testErr; // 测试通过后再换回Firebase代码 // const user = await firebase.auth().createUserWithEmailAndPassword(email, password); // return user; };
如果这样Saga能进入catch分支,说明是Firebase的邮箱验证规则和你的预期有差异,需要调整你对“无效邮箱”的判断逻辑(比如在调用doRegister前先做前端邮箱格式校验)。
4. 检查Saga的调用方式
确保你是用yield call(signupSaga, action)或者在watchSaga里用takeLatest等effect来调用,而不是用fork——fork是非阻塞的,不会等待异步操作完成,也不会捕获它的错误,会直接继续执行后面的代码。
内容的提问来源于stack exchange,提问作者domi

