简体   繁体   中英

Wait for Firebase data to load before rendering NodeJS page after forEach with Promise.all()

I'm trying to create a page that loads multiple data sets from Firebase, and then passes them to the NodeJS rendered page. I'd appreciate some help in ensuring that this happens after the forEach iterations; namely, I'm not sure how to get the Firebase forEach iterations to be part of my promises.

Thank you so much!

router.get('/', function(req, res, next) {

    var getBrands = brandRef.once('value').then(function(snapshot){
        var brands = [];

        snapshot.forEach(function(childSnapshot){
            console.log(childSnapshot.val()['name']);
            brands.push({'name' : childSnapshot.val()['name'] });
        });

        return brands;
    });
    var getStores = storeRef.once('value').then(function(snapshot){
        var stores = [];

        snapshot.forEach(function(childSnapshot){
            stores.push({'name' : childSnapshot.val()['name'] });
        });

        return stores;
    });
    var getProducts = productRef.once('value').then(function(snapshot){
        var products = [];

        snapshot.forEach(function(childSnapshot){
            products.push({'name' : childSnapshot.val()['name'] });
        });

        return products;
    });

    console.log(brands, stores, products);
    Promise.all([getBrands, getStores, getProducts]).then(function(results){

        res.render('index', { title: 'MStore Demo Portal', stores: results[0], brands: results[1], products: results[2] });
    });
});

Your code looks 99% OK

router.get('/', function(req, res, next) {
    var getBrands = ...;
    var getStores = ...;
    var getProducts = ...;

So far so good (didn't even bother copying the code, because it's correct

    console.log(brands, stores, products);

brands, stores and products are declared inside the .then callbacks, so regardless of anything, they'll always be undefined at this point

    Promise.all([getBrands, getStores, getProducts]).then(function(results){

        res.render('index', { title: 'MStore Demo Portal', stores: results[0], brands: results[1], products: results[2] });
    });
});

The only "issue" above is that results will be brands, stores, products due to your order of getBrands, getStores, getProducts in Promsie.all

However, you seem to think (based on the index) that the results will be stores, brands, products - either swap indices 0 and 1 in the code, or call

Promise.all([getStores, getBrands, getProducts]).then

a tip, if you're using a recent enough node.js, you can do the following

Promise.all([getStores, getBrands, getProducts]).then(([stores, brands, products]) =>
    res.render('index', { title: 'MStore Demo Portal', stores, brands, products })
);

Firebase is designed to be a serverless architecture. In the long run, you shouldn't need a standard RESTFul Node.js API server. You just need Lambda workers. Please see: https://github.com/firebase/firebase-queue

Put work on the queue and a worker will pick up the job and update Firebase. When Firebase updates, it will send your front-end the message. It's all asynchronous and should work well for almost any application.

There's nothing wrong with having an API server too, but really it's not needed. Unless you have a very good reason for having what I assume to be an Express API server, then you can ditch it.

It looks like all you are doing with this code is getting values from the DB, you can do this with the front-end instead of an API server, and merge the results on the front-end, it's much better to do things that way.

Literally, just take the code that's in Express here, and move it to your front-end app :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM