2

This function will return the value of initiate_session, initiate_session[user_session].events, user_session before the firebase function runs.

How to run the firebase function first ??

function createSession() {
var user_session = randomCharacters(20) //8iKhA4Aq2!6gZ)890ip@;
var ip = '127.0.0.1';
var initiate_session = new Object();
var session_started = new Date().getTime();


firebase.database().ref(user_session).once('value', function (snapshot) {
    if (snapshot.exists()) {
        console.log('session exists');
        createSession();
    } else {
        console.log('session not exists')

        initiate_session[user_session] = {
            ip: ip,
            session_started: session_started,
            events: {}
        };

        firebase.database().ref(user_session).set({
            ip: ip,
            session_started: session_started,
            events: {}
        });
    }
});

console.log('new session', initiate_session);
return [initiate_session, initiate_session[user_session].events, user_session];}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

2

This is because the Firebase function is asynchronous - the code inside the method that gets the snapshot is a callback that is executed after the Firebase read is finished, which may take several seconds. However, as soon as you dispatch the read request via .once(...) your execution flow continues and the return is called.

There are a few possible solutions:

  1. Pass a callback argument to your createSession() method that is called with the values you are trying to return, instead of returning them directly.

  2. Return a promise from your method that resolves to give the values you're trying to return.

  3. Use async/await syntax for your Firebase call. This is covered already in this question: running queries in firebase using async / await

Rough Example of #1

function createSession(onSessionCreated) {
    var user_session = "whatever";
    var initiate_session = new Object();

    firebase.database().ref(user_session).once('value', function (snapshot) {
        // do things with the snapshot
        onSessionCreated(initiate_session, initiate_session[user_session].events, user_session)
    });
}

// usage:
createSession(function (initiate_session, events, user_session) {
    // do things with initiate_session, events and user_session
});

Rough Example of #2

function createSession() {
    var user_session = "whatever";
    var initiate_session = new Object();

    firebase.database().ref(user_session).once('value').then(function (snapshot) {
        // do things with the snapshot
        return [initiate_session, initiate_session[user_session].events, user_session];
    });
}

// usage:
createSession().then(function (results) {
    // do things with results (i.e. the three elements in the array above)
});

Rough Example of 3

async function createSession() {
    var user_session = "whatever";
    var initiate_session = new Object();

    const snapshot = await firebase.database().ref(user_session).once('value');
    // do things with the snapshot

    return [initiate_session, initiate_session[user_session].events, user_session];
}

// usage:
const results = await createSession();

If you're new to async/await code it probably won't be the easiest place to start as it may require changes elsewhere in your code, but this article is a good resource if you're keen to learn.

Mark Ormesher
  • 2,289
  • 3
  • 27
  • 35
  • `const results = await createSession();` await should be inside async? – Ilyas karim Jan 06 '19 at 12:05
  • 1
    Yes, that would need to be inside an `async` section. – Mark Ormesher Jan 06 '19 at 12:12
  • `const session = await createSession();` `async function createSession() { var user_session = randomCharacters(20) //8iKhA4Aq2!6gZ)890ip@; var ip = '127.0.0.1'; var initiate_session = new Object(); var session_started = new Date().getTime(); var snapshot = await firebase.database().ref(user_session).once('value'); //Some codes return [initiate_session, initiate_session[user_session].events, user_session]; }` result: `Uncaught SyntaxError: await is only valid in async function` – AbdulaziAlswaji Jan 06 '19 at 12:18
  • @AbdulaziAlswaji As I said, using the `async`/`await` patter might require changes elsewhere in your codebase, so it probably won't be the easiest solution if you're not using `async` code already. Solutions #1 and #2 will require fewer changes to existing code, so you might want to start with one of them. – Mark Ormesher Jan 06 '19 at 12:23