0

I am trying to read data from firebase . But the code works asynchronously and it displays data before fetching it .

I have posted my code

componentDidMount(){
    var ref2 = database.ref();
    this.getItems(ref2).then((items) => {
        this.getResult(items).then((val) => {
            // why is this val coming empty 
            ToastAndroid.show(JSON.stringify(val), ToastAndroid.SHORT);
        });
    });
  }

getItems = async (ref2) => {
    var items = [];
    await ref2.once('value', snap => {
        snap.forEach((child) => {
            items.push(child.key);
        });
    });

    // this is working fine . items is correctly returned        
    return items;
}
getResult = async (items) => {
    var response = await this.getFinal(items); 
    // this response is empty why 
    return response;
}
getFinal = async (items) => {
    var result = [];
    await items.forEach((key) => {
        ref = database.ref(key);
        ref.once('value', snap => {

            snap.forEach((child) => {
                //val.push(child.val());
                var id = child.key;
                var data = {
                    username: child.val().username,
                    email: child.val().email,
                    name: child.val().name
                };
                result.push({[id]:data});    
            });
        });
    });
    // this result is empty why   
    return result;
}

I am expecting val to be not empty and also the result to be not empty

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • You are calling ``await items.forEach...`` in the method ``getFinal``. ``[Array].forEach`` is not asynchronous. Also see: https://stackoverflow.com/a/5050317/2692307 – Lukas Bach Aug 11 '19 at 13:15
  • Thanks a lot for pointing this out. I really overlooked this part – kanhaiyabgs Aug 11 '19 at 16:29
  • You are also awaiting a `.once()`. The `.on()` and `.once()` patterns are registering event handlers on an EventEmitters - they don't return Promises. Promise and EventEmitters are two different design patterns for handling asynchronous program flow. As such `await` does not work with `.once()` – slebetman Aug 11 '19 at 17:11

1 Answers1

1

As Lukas commented Array.forEach() does not return a promise, so calling await on it doesn't do anything useful.

The DatabaseReference.once() call however does return a promise, and since you have multiple of those calls, you can gather the promises and wait for all of those to finish before returning the result:

getFinal = async (items) => {
    var promises = [],
        result = [];
    items.forEach((key) => {
        ref = database.ref(key);
        let promise = ref.once('value', snap => {
            snap.forEach((child) => {
                var id = child.key;
                var data = {
                    username: child.val().username,
                    email: child.val().email,
                    name: child.val().name
                };
                result.push({[id]:data});    
            });
        });
        promises.push(promise)
    });
    await Promise.all(promises);
    return result;
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807