user12810571
user12810571

Reputation:

App hangs after writing to database due to while loop

I have a user_dict object that is created by downloading some data from a Firebase database. Immediately after that user_dict object is created, I save an instance of it within a profile child saved under the uid.

The needed info is being correctly saved to my database, but my is_profile_ready bool never returns true and I get stuck in my while loop. Is there a better way to handle this? I know this is bad form but I've struggled to get promises and async/await working properly.

Is this due to my while loop, or am I doing something else wrong to keep is_profile_ready from ever returning 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 })
}

Edit: Frank suggested a solution which I'm getting an error (cannot read property "then" of undefined) on is_profile_ready.then. Copying the code below for easier reading.

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 })
}

Upvotes: 0

Views: 43

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598837

You seem to think that your createProfile function returns true. But if you'd actually log the return value, you'll see it's a more complex object known as a Promise, which is a promise that it'll have a value in the future.

To wait for that value, you can either use await or you can listen to the then function of the promise like this:

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()
})

Update: for this to work, it is important to return the promise from the top level of your createProfile function, so:

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 })
}

Upvotes: 2

Related Questions