Making Firebase query act synchronous

时间:2018-06-19 11:13:43

标签: javascript reactjs firebase firebase-realtime-database

I'm building a simple testing site. How it works: A user accepts a task (assignment), sends an answer, which is then pushed to an array called answers.

What I need to do, is check if the answers array in the assignment object is defined. If it is it means user has submitted at least one answer and he's good to submit.

The problem is the async. I'm not sure how to make the code wait for the query to finish.

Here's my code:

export default class FinishAnswerButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.handleFinishAssignment = this.handleFinishAssignment.bind(this);
    }

    async handleFinishAssignment() {
        var currentAssignment = firebase.database().ref('Works').child(this.props.assignmentId);
        console.log('props points', this.props.points);
        var outerThis = this;
        await currentAssignment.on('value', snapshot => {
            console.log(snapshot.val());
        });
        var user = firebase.database().ref('Users').child(firebase.auth().currentUser.uid);
        await user.once('value', snapshot => {
            var acc = snapshot.val();
            var points = outerThis.props.points + acc.points;
            user.child('points').set(points).catch(e => console.log(e));

            // user.child('assignedWork').remove().catch(e => console.log(e));
            // currentAssignment.child('state').set('Completed').catch(e => console.log(e));
            // currentAssignment.child('finishTime').set(Time.generate()).catch(e => console.log('finishTime', e));
        });
        return <AssignmentsComponent/>
    }

    render() {
        return (
            <Button onClick={this.handleFinishAssignment}>Zakoncz rozwiazywanie zadania (Upewnij
                sie ze uczen ma wszystko czego potrzebuje!)</Button>
        )
    }
}

I tried solving it like this:

async handleFinishAssignment() {
    var currentAssignment = firebase.database().ref('Works').child(this.props.assignmentId);
    console.log('props points', this.props.points);
    var outerThis = this;
    currentAssignment.once('value', snapshot => {
        console.log(snapshot.val());
        return snapshot.val();
    }).then(assignment => { // here
        console.log(assignment);
        var user = firebase.database().ref('Users').child(firebase.auth().currentUser.uid);
        if (assignment.answers.length > 0) {
            console.log('if');
            user.once('value', snapshot => {
                var acc = snapshot.val();
                var points = outerThis.props.points + acc.points;
                user.child('points').set(points).catch(e => console.log(e));
                // user.child('assignedWork').remove().catch(e => console.log(e));
                // currentAssignment.child('state').set('Completed').catch(e => console.log(e));
                // currentAssignment.child('finishTime').set(Time.generate()).catch(e => console.log('finishTime', e));
            }).catch(e => console.log(e));
        } else
            console.log('else');
    });
    return <AssignmentsComponent/>
}

But it turned out, the assignment passed to the callback is a promise, not the actual snapshot.val(), which is basically what I need in the next part of the code.

Also, why does adding await not solve the issue? I thought the whole idea of await is to make the code act synchronously. Or am I using it wrong?

So to recap: I need to make this code wait. I need to use the response from the await currentAssignment.on('value', snapshot => { to be available in the next query, which is: await user.once('value', snapshot => {. How can I achieve this?

1 个答案:

答案 0 :(得分:0)

好吧,我知道了。我在正确的轨道上,但是在途中遇到了精神障碍。这是工作代码:

async handleFinishAssignment() {
    var currentAssignment = firebase.database().ref('Works').child(this.props.assignmentId);
    var outerThis = this;
    currentAssignment.once('value').then(snapshot => { // Right here
        var assignment = snapshot.val();
        console.log(assignment);
        var user = firebase.database().ref('Users').child(firebase.auth().currentUser.uid);
        if (assignment.answers !== undefined) {
            console.log('if');
            user.once('value', snapshot => {
                var acc = snapshot.val();
                var points = outerThis.props.points + acc.points;
                user.child('points').set(points).catch(e => console.log(e));
                // user.child('assignedWork').remove().catch(e => console.log(e));
                // currentAssignment.child('state').set('Completed').catch(e => console.log(e));
                // currentAssignment.child('finishTime').set(Time.generate()).catch(e => console.log('finishTime', e));
            }).catch(e => console.log(e));
        } else
            console.log('else');
    });
    return <AssignmentsComponent/>
}