Firebase onAuthStateChanged取消订阅递归

tmv*_*nty 1 javascript recursion firebase firebase-authentication redux

我有这段代码检查用户是否已在Firebase中登录,如果是,请使用Redux调度操作并将状态更新为当前的auth用户.

/**
 * check to see if the user has signed in already or not
 */
function initAuth(dispatch) {
  return new Promise((resolve, reject) => {
    const unsubscribe = firebase.auth().onAuthStateChanged(
      authUser => {
        dispatch({ type: "INIT_AUTH", payload: authUser });
        unsubscribe();
        resolve();
      },
      error => reject(error)
    );
  });
}
initAuth(store.dispatch)
  .then(() => render())
  .catch(error => console.error(error));
Run Code Online (Sandbox Code Playgroud)

我感到困惑的是,为什么在取消订阅中调用unsubscribe()?我知道你可以像在JavaScript递归中那样做,但这里有什么用?谢谢!

CRi*_*ice 8

onAuthStateChanged接受一个函数,因为它是唯一的参数.该函数是在auth状态更改时将调用的函数.所以代码

function printHelloWorld() {
    console.log("Hello World")
}

firebase.auth().onAuthStateChanged(printHelloWorld)
Run Code Online (Sandbox Code Playgroud)

"Hello World"只要auth状态发生变化,就会打印到控制台.但是,在稍后的某个时间,我们想要停止执行该功能,因为我们已经做了我们需要的任何事情.如果你熟悉事件监听器,他们使用一个模式去除一个,你可以调用类似的东西removeEventListener.但firebase没有offAuthStateChanged或有一些这样的.相反,onAuthStateChanged函数返回一个函数,你退订您最初给它的功能.要清楚,它不会返回您的原始函数(您给出的函数,因此printHelloWorld在此示例中),但会返回一个可用于删除原始函数的函数.

所以回到这个例子:

function printHelloWorld() {
    console.log("Hello World")
}

var unsubscribe = firebase.auth().onAuthStateChanged(printHelloWorld)

// ... Sometime later when we are no longer interested in auth changes
unsubscribe();
// From this point forward, when the auth state changes, printHelloWorld will no longer be triggered.
Run Code Online (Sandbox Code Playgroud)

最后,假设您只想让一个函数在auth更改上运行,但只有一次.最简单的方法是让它运行一次,然后取消订阅.所以代码:

var unsubscribe = firebase.auth().onAuthStateChanged(() => {
    console.log("Hello World")
    unsubscribe()
})
Run Code Online (Sandbox Code Playgroud)

表示第一次使用auth状态更改时,我们将记录该字符串,然后立即取消订阅进一步的更改.因此,通过在函数本身内调用取消订阅,我们只是说,运行一次,然后删除自己.

另外,请注意您可以在函数的开头或结尾调用取消订阅,这没关系.整个函数体将像其他任何一样执行.所以调用unsubscribe不会停止执行函数的其余部分,或类似的东西.

这就是为什么这样的事情

var unsubscribe = firebase.auth().onAuthStateChanged(() => {
    unsubscribe()
    // Lots of other code here...
});
Run Code Online (Sandbox Code Playgroud)

是这样一种常见的模式.


小智 6

如果您只想听一次用户身份验证状态的变化,您必须这样做:

const unsubscribe = firebase.auth().onAuthStateChanged((user) => { 
    if(unsubscribe) {
      unsubscribe();
    }
 }
Run Code Online (Sandbox Code Playgroud)

似乎侦听器运行了两次,第一次是在创建时,第二次是在用户实际更改其状态时。第一次unsubscribe未定义,因此您在运行之前检查已定义。