为什么我的容器组件无法正确接收 Async Await 的结果?
这让我有点抓狂。
预期行为:
我点击一个按钮 > 它触发 checkLoginStatus > 从 firebase 返回 true 或 false > 布尔值存储在 isLoggedIn > 中,即 console.log 输出
实际结果: 我点击按钮 > 它触发函数 > 控制台日志显示为未定义/false > 然后返回用户对象。
问题:
为什么我的 React 容器方法
isUserAlreadyAuthenticated()
在
await
完成之前注销?
上下文:
我有一组 4 个实用函数。它们每个都专注于 firebase/login 生命周期中的不同元素(注册、登录、注销、hasUserAuthenticatedBefore...)
它们都是 async-await 函数。例如:这是登录函数 - 运行良好:-
export const login = async (email, password) => {
let defaultStatus = false;
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
.then(res => {
// if firebase fires back a user object, then login is true.
if (res.user.email) {
defaultStatus = true;
}
})
.catch(error => {
console.log('Firebase | sign in error: ', error.message);
defaultStatus = false;
});
} catch (err) {
console.log('Login | error: ', err);
}
console.log('login status after logging in Try/Catch is: ', defaultStatus);
return defaultStatus;
}
注意:当我在容器中调用此函数时,它会获得正确的布尔响应。
现在...如果我查看 checkLoginStatus 函数。没有任何变化或奇怪而精彩的重写可以使其以类似的方式运行。
export const checkLoginStatus = async () => {
let defaultStatus = false;
try {
firebase.auth().onAuthStateChanged(user => {
// if user exists then defaultStatus = true;
// if not exists then defaultStatus = false;
})
} catch (err) {
console.log('sign up user error: ', err);
}
console.log('default status after checking login status: ', defaultStatus);
return defaultStatus;
}
然后在我的容器中:-
isUserAlreadyAuthenticated = async () => {
let isLoggedIn = await this.props.checkLoginStatus();
console.log('is foo here? ===>', isLoggedIn); // undefined
}
我尝试过的事情:-
将实用程序函数更改为承诺(这会导致 checkLoginStatus 不是函数错误)
从 isUserAlreadyAuthenticated 中删除异步;像普通函数一样触发它(因为异步部分在实用程序函数本身中进行管理)。没有乐趣。
将 onAuthStateChanged() api 更改为
.then()
样式的承诺。没有变化。
我从
checkLoginStatus
中删除了所有 Firebase 代码 &只是让它在
setTimeout()
之后返回一个字符串 - 并且它仍然
在检索到用户对象之前返回未定义
。
我在这里看不到什么?
感谢 @FelixKling 和 @Think-Twice 。
我最终确实 a) 将 util 函数包装在 Promise 中, 并且 阅读了 async await。我以为我理解了这一点,但有一些怪癖我并没有理解。
关键似乎是放入了一个递归元素。
util 函数:
export function checkLoginStatus() {
return new Promise((resolve, reject) => {
const unsubscribe = firebase.auth().onAuthStateChanged(user => {
unsubscribe(); // <--- calls itself and resolves with a successful user object or null
resolve(user);
}, reject('api has failed'));
});
}
这会调用自身,直到用户响应是成功的用户对象或返回 null。
在 React 方面,我有一个 Async-Await 函数来等待承诺:
isUserAlreadyAuthenticated = async () => {
try {
let user = await this.props.checkLoginStatus();
console.log('react side: ', user);
if (user && user.email) {
this.setState({
isLoggedIn: true, // <-- when true page navs to Homepage
});
}
} catch(err) {
console.log('catch | api error: ', err);
}
}
我希望这对其他正在使用
onAuthStateChanged()
api 的人有所帮助。它不是承诺,它不是可执行的。它必须采用回调。