【问题标题】:App hangs after writing to database due to while loop由于while循环,应用程序在写入数据库后挂起
【发布时间】:2021-07-13 19:01:12
【问题描述】:

我有一个 user_dict 对象,它是通过从 Firebase 数据库下载一些数据而创建的。创建该 user_dict 对象后,我立即将它的一个实例保存在该 uid 下保存的配置文件子项中。

所需信息已正确保存到我的数据库中,但我的 is_profile_ready bool 永远不会返回 true,并且我陷入了我的 while 循环。有没有更好的方法来处理这个?我知道这是不好的形式,但我一直在努力让 Promise 和 async/await 正常工作。

这是由于我的 while 循环,还是我做错了什么来阻止 is_profile_ready 返回 true?

async function handleTestStart() {
    traceFunction()
    character.style.backgroundImage = "url(character.png)"
    left_button.style.visibility = 'visible'
    right_button.style.visibility = 'visible'
    showLogoAnimation()
    setTimeout(function () {
        let start_time = new Date().getTime()
        while (!is_user_dict) {
            let end_time = new Date().getTime()
            let time = end_time - start_time
            if (time > 10000) {
                timeoutError()
            }
        }
        let is_profile_ready = createProfile()
        let start_time2 = new Date().getTime()
        while (!is_profile_ready) {
            let end_time2 = new Date().getTime()
            let time2 = end_time2 - start_time2
            if (time2 > 10000) {
                timeoutError()
            }
        }
        hideLogoAnimation()
        condition_category_array.forEach(function (condition_category) {
            user_dict['more_info'].push(condition_category)
        })
        category = user_dict['more_info'][0]
        backup_user_dict = deepCopyObject(user_dict)
        nextQuestion()
    }, 2000)
}

function createProfile() {
    let current_user_id = firebase.auth().currentUser.uid
    console.log('createProfile currentUser is ', current_user_id)
    firebase.database().ref().child('profile').child(current_user_id).set({
        'user_dict' : user_dict
    }).then(() => { return true })
}

编辑:弗兰克提出了一个解决方案,我在 is_profile_ready.then 上遇到错误(无法读取未定义的属性“then”)。复制以下代码方便阅读。

async function handleTestStart() {
    traceFunction()
    character.style.backgroundImage = "url(character.png)"
    left_button.style.visibility = 'visible'
    right_button.style.visibility = 'visible'
    showLogoAnimation()
    let start_time = new Date().getTime()
    while (!is_user_dict) {
        let end_time = new Date().getTime()
        let time = end_time - start_time
        if (time > 10000) {
            timeoutError()
        }
    }
    let is_profile_ready = createProfile()
    let start_time2 = new Date().getTime()
    is_profile_ready.then((result) => {
        let end_time2 = new Date().getTime()
        let time2 = end_time2 - start_time2
        if (time2 > 10000) {
            timeoutError()
        }
        hideLogoAnimation()
        condition_category_array.forEach(function (condition_category) {
            user_dict['more_info'].push(condition_category)
        })
        category = user_dict['more_info'][0]
        backup_user_dict = deepCopyObject(user_dict)
        nextQuestion()
    })
}

function createProfile() {
    let current_user_id = firebase.auth().currentUser.uid
    console.log('createProfile currentUser is ', current_user_id)
    firebase.database().ref().child('profile').child(current_user_id).set({
        'user_dict': user_dict
    }).then(() => { return true })
}

【问题讨论】:

    标签: javascript firebase firebase-realtime-database


    【解决方案1】:

    您似乎认为您的createProfile 函数返回true。但是,如果您实际记录返回值,您会看到它是一个更复杂的对象,称为 Promise,它承诺它在未来会有一个值。

    要等待该值,您可以使用await,也可以像这样收听promise 的then 函数:

    let is_profile_ready = createProfile()
    let start_time2 = new Date().getTime()
    is_profile_ready.then((result) => {
        let end_time2 = new Date().getTime()
        let time2 = end_time2 - start_time2
        if (time2 > 10000) {
            timeoutError()
        }
        hideLogoAnimation()
        condition_category_array.forEach(function (condition_category) {
            user_dict['more_info'].push(condition_category)
        })
        category = user_dict['more_info'][0]
        backup_user_dict = deepCopyObject(user_dict)
        nextQuestion()
    })
    

    更新:要让它工作,从createProfile函数的顶层返回promise很重要,所以:

    function createProfile() {
        let current_user_id = firebase.auth().currentUser.uid
        console.log('createProfile currentUser is ', current_user_id)
        return firebase.database().ref().child('profile').child(current_user_id).set({
            'user_dict': user_dict
        }).then(() => { return true })
    }
    

    【讨论】:

    • 谢谢弗兰克,但是当我尝试使用承诺时,我得到了“无法读取未定义的属性”,这发生在我身上很多。我更新了上面的代码以显示我的尝试,我添加了一个右括号,因为我假设它是无意中遗漏的。
    • 我添加了如何实现createProfile,但绝对也建议阅读我提供的链接,因为它们清楚地说明了您的代码为什么不起作用。
    • 明白了,这实际上很有意义。不过,我会阅读更多内容,感谢您的帮助。
    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2015-12-22
    • 2016-10-21
    • 2012-05-13
    相关资源
    最近更新 更多