Search code examples
node.jsfirebaseexpressgoogle-cloud-firestorees6-promise

how to export array created in a promise


I'm trying to follow a project from mozilla developer local library tutorial . It includes learning how to use nodejs, express, mongoose and mongoDB. I am swapping out mongoose and mongoDB with firestore and using firebase functions to eventually host with firebase hosting.

The project uses a model, view, controller structure. I really want to stick to this structure to help break everything down into manageable chunks.

The first problem I’m trying to resolve is to return an array that I created in a promise to be exported as a function that is called from booksController.js.

A concise view of the structure I have is: index.js

const booksRouter = require('./routes/books');
app.use('/books', booksRouter);

routes/books.js

const books_controller = require('../controllers/booksController');
router.get('/', books_controller.index);

controllers/booksController.js

var Books = require('..models/books');
exports.index = function(req, res){
    var books = Books.AllBooks();
    res.render('books',{books: books});
};

models/books.js

var booksRef = db.collection(books);
var allBooks = booksRef.get()
    .then(snapshot => {
        var books = [];
        Snapshot.forEach(doc => {
            books.push({doc.data: doc.data()});
        });

    });
.catch(err =>{
    console.log('Error getting documents', err);
});
exports.AllBooks = function(req, res){
    return books;
}

I've tried wrapping the promise in a function and returning the array to export it but I get undefined when console logging in booksController.js.

Can someone please enlighten me and complete the puzzle of how to return the array so it can be exported.


Solution

  • What you're trying to do, can't be done using require, since require is synchronous.

    Instead what you can do is export a function that will fetch the books asynchronously, and use that function in your controller.

    models/books.js

    const booksRef = db.collection(books);
    
    async function getBooks() {
    
        // You can implement a cache and fetch the books only once.
        const snapshot = await booksRef.get()
    
        const books = [];
        snapshot.forEach(doc => {
            books.push({
                doc.data: doc.data()
            });
        });
    
        return books;
    
    }
    
    module.exports = getBooks;
    

    controllers/booksController.js

    const getBooks = require('./../models/books');
    exports.index = async function(req, res){
        const books = await getBooks(); // Handle exception
        res.render('books',{books: books});
    };