这让我有点发疯。
预期行为:
我单击一个按钮>触发checkLoginStatus>从firebase返回true或false>布尔值存储在isLoggedIn>中,即console.log'd
实际结果: 我单击按钮>它将关闭功能>控制台日志显示为undefined / false>然后返回用户对象。
问题:
为什么我的React容器方法isUserAlreadyAuthenticated()
在await
完成之前退出了?
上下文:
我有一组4个实用程序功能。他们每个人都专注于firebase / login生命周期中的diff元素(注册,登录,注销,hasUserAuthenticatedBefore ...)
它们都是异步等待功能。因此,例如:这是登录名-可以正常工作:-
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
}
我尝试过的事情:-
将util函数更改为Promise(这将得到checkLoginStatus并非函数错误)
从isUserAlreadyAuthenticated中删除异步;像正常函数一样触发它(因为异步部分是在util函数本身中管理的)。不高兴。
将onAuthStateChanged()api更改为.then()
样式的承诺。没有变化。
我从checkLoginStatus
中删除了所有Firebase代码,只是让它在setTimeout()
之后返回了一个字符串-仍然在检索用户对象之前返回undefined 。
我在这里没看到什么?
答案 0 :(得分:1)
感谢@FelixKling和@ Think-Twice。
我实际上确实结束了a)将util函数包装在Promise中,和在异步等待时读取。以为我明白了,但是我没有一些怪癖。
关键似乎是放在递归元素中。
实用功能:
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进行操作的其他人有所帮助。这不是一个承诺,这是无法解决的。它必须进行回调。