简体   繁体   English

登录和注销时多次从firestore获取数据(vanilla JS)

[英]Data from firestore it's being fetched multiple times when login and logout (vanilla JS)

Well I made this Library app, where an user can login and add books.好吧,我制作了这个图书馆应用程序,用户可以在其中登录和添加书籍。 So, when a user login the app fetch data from a firestore collection, cool.因此,当用户登录应用程序从 Firestore 集合中获取数据时,很酷。 The problem exists when the user login once, logout and then login again without refreshing the app.当用户登录一次,注销然后再次登录而不刷新应用程序时,就会出现问题。 If the user do this twice, the fetch twice, if thrice, the fetch thrice.如果用户这样做两次,则获取两次,如果三次,则获取三次。 The code that executes multiple times its the fetchBooks() , the signInWithGoogle() only executes once.多次执行的代码是fetchBooks() ,而signInWithGoogle()只执行一次。 Here's the code involved:这是涉及的代码:


function signInWithGoogle(){
    const provider = new firebase.auth.GoogleAuthProvider()
        auth.signInWithPopup(provider)
            .then(result => {
                // Create the new user document in firestore
                createNewUserDocument(result.user)
                // fetch feed data
                auth.onAuthStateChanged(user =>{
                    user? fetchBooks() : null
                })
            }).catch(err => {
                console.log(err)
            })
        signUpForm.reset()
        signUpModal.hide()
        signInForm.reset()
        signInModal.hide()
}


function fetchBooks() {
    const docRef = db.collection('users').doc(auth.currentUser.uid).collection('books')
    docRef.get().then(querySnapshot =>{
        console.log(querySnapshot)
        querySnapshot.forEach(doc => {
            const data = doc.data()
            console.log(doc.data());
            addCardToHTML(data.title, data.author, data.pages, data.description, data.read)
        })
    })
}

onAuthStateChanged is a subscription that triggers itself when there's a change in the user's authentication state. onAuthStateChanged是一种订阅,当用户的身份验证 state 发生更改时,它会自行触发。

So it will trigger when you log in, when you log out, etc.所以它会在你登录、注销等时触发。

So ideally you'd want to wait until the user logs in, and then call the fetchBooks() function, but if you keep doing it inside of the subscriber the function will trigger any time the subscriber emits a new value.因此,理想情况下,您希望等到用户登录,然后调用fetchBooks() function,但如果您继续在订阅者内部执行此操作,则 function 将在订阅者发出新值时触发。

I would recommend starting with a restructure of your code to have functions that do individual things.我建议从重组代码开始,使其具有执行个别操作的功能。 Right now, you have a function signInWithGoogle .现在,您有一个 function signInWithGoogle That function should only sign the user in with Google and return a promise with the result of that sign in. Instead, you have it signing in the user, fetching books (which itself is also fetching books AND modifying the DOM), and calling methods on your signUp elements.那个 function 应该用谷歌登录用户并返回一个带有登录结果的 promise。相反,你让它登录用户,取书(它本身也是取书和修改 DOM),并调用方法在您的注册元素上。

Restructuring this to have some other top-level function would likely help you handle your problem easier.将其重组为具有其他一些顶级 function 可能会帮助您更轻松地处理您的问题。 Specifically, try something like this:具体来说,尝试这样的事情:

function handleSignIn() {
    signInWithGoogle()
        .then(fetchBooks)
        .then(books => {
            books.forEach(book => addCardToHTML(...))
        })
}

This is a good start because now it's clear what each individual function is doing.这是一个好的开始,因为现在很清楚每个单独的 function 在做什么。 So now to handle your specific issue, I'll assume that the problem you're facing is that you're seeing the books be added multiple times.因此,现在要处理您的具体问题,我假设您面临的问题是您看到书籍被多次添加。 In that case, I would think what you'd want to happen is that:在那种情况下,我认为你想要发生的是:

  1. When a user is signed in, you want to load their books and display them on the page.当用户登录时,您希望加载他们的书籍并将其显示在页面上。
  2. When they log out, you want the books to be unloaded from the screen当他们注销时,您希望将书籍从屏幕上卸载
  3. When they log back in, the books are re-loaded and displayed.当他们重新登录时,书籍会重新加载并显示。

If all of those assumptions are correct, then your problem wouldn't be with the code you have, but rather the signout functionality.如果所有这些假设都是正确的,那么您的问题将不在于您拥有的代码,而在于登出功能。 When the user signs out, you need to add a function that will remove the books from the HTML.当用户注销时,您需要添加一个 function,它将从 HTML 中删除书籍。 That way, when they sign back in after signing out, the handleSignIn function will kick off again and the addCardToHTML function will be running on a blank HTML page rather than a page that already has the cards.这样,当他们在退出后重新登录时,handleSignIn function 将再次启动,并且 addCardToHTML function 将在空白 Z4C4AD5FCA2E7A3F74DBB1CED00381AA4 页面上运行,而不是在已经有卡片的页面上运行。

Example:例子:

function handleSignOut() {
    signOut()
        .then(clearBookCards)
}

function clearBookCards() {
    // Manipulate DOM to remove all of the card HTML nodes
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM