调用loginUser时SecureStore未执行,直接返回axios.post结果问题排查
我调用loginUser函数时,预期会执行SecureStore相关操作,但实际直接返回了axios.post方法的结果,未进入SecureStore的处理逻辑。请问问题出在哪里?
import { SecureStore } from 'expo'; export function loginUser(email, password) { return function (dispatch) { return axios.post(SIGNIN_URL, { email, password }).then((response) => { var { user_id, token } = response.data; Expo.SecureStore.setItemAsync(user_id, password, options).then(function() { dispatch(authUser(user_id)); console.log('I am in') }).catch((error) => { console.log('Its an error') dispatch(addAlert("Could not log in.")); }); }).catch((error) => { dispatch(addAlert("Could not log in.")); }); }; }
问题分析与解决方案
咱们一步步拆解问题,找到根源:
1. SecureStore的引用不一致
你开头通过import { SecureStore } from 'expo'导入了SecureStore,但代码里却用了Expo.SecureStore——如果你的项目环境中没有全局挂载Expo对象,这会直接抛出引用错误,导致setItemAsync的逻辑根本无法执行,直接跳转到外层的catch块。
修复:统一使用导入的SecureStore:
SecureStore.setItemAsync(user_id, password, options)
2. 未返回SecureStore的Promise链
当前代码中,axios.post的then回调里执行了setItemAsync,但没有return这个Promise。这意味着loginUser返回的Promise会在axios.post完成后就立即resolve,而SecureStore的异步操作还在后台执行——你看到的“直接返回axios结果”就是这个原因,调用者会误以为整个流程已经完成,但SecureStore的逻辑其实还没跑完(甚至可能因为前面的错误根本没启动)。
修复:return setItemAsync的Promise链,让整个异步流程连贯起来:
return axios.post(SIGNIN_URL, { email, password }).then((response) => { var { user_id, token } = response.data; // 这里加上return,把SecureStore的Promise链传递出去 return SecureStore.setItemAsync(user_id, password, options).then(function() { dispatch(authUser(user_id)); console.log('I am in') }).catch((error) => { console.log('Its an error', error) // 打印具体错误信息,方便排查 dispatch(addAlert("Could not log in.")); }); })
3. options变量未定义
你调用setItemAsync时传入了第三个参数options,但代码里完全没有定义这个变量。这会导致参数错误,触发setItemAsync的catch块,虽然你有错误处理,但这也是SecureStore逻辑未按预期执行的潜在问题。
修复:如果不需要额外存储选项,直接去掉这个参数;如果需要自定义存储规则,先定义options:
// 方案1:不需要额外选项时去掉参数 return SecureStore.setItemAsync(user_id, password).then(...) // 方案2:定义options(比如设置iOS钥匙串的访问权限) const options = { keychainAccessible: SecureStore.WHEN_UNLOCKED }; return SecureStore.setItemAsync(user_id, password, options).then(...)
修复后的完整代码
import { SecureStore } from 'expo'; import axios from 'axios'; // 确保导入axios,假设SIGNIN_URL、authUser、addAlert均已正确定义 export function loginUser(email, password) { return function (dispatch) { return axios.post(SIGNIN_URL, { email, password }) .then((response) => { const { user_id, token } = response.data; // 可选:定义存储选项 const options = { keychainAccessible: SecureStore.WHEN_UNLOCKED }; // 返回SecureStore的Promise链,保证流程完整 return SecureStore.setItemAsync(user_id, password, options) .then(() => { dispatch(authUser(user_id)); console.log('I am in'); }) .catch((error) => { console.log('SecureStore操作错误:', error); // 打印具体错误 dispatch(addAlert("无法保存登录凭证,请重试。")); }); }) .catch((error) => { console.log('登录请求错误:', error); // 打印请求错误细节 dispatch(addAlert("登录失败,请检查账号密码或网络连接。")); }); }; }
另外,建议在所有catch块中打印具体错误信息,这样能快速定位到底是请求失败、SecureStore操作失败还是其他语法问题。
内容的提问来源于stack exchange,提问作者Markus Hayner

