Search code examples
node.jsfirebasegoogle-cloud-firestoregoogle-cloud-functionspdfmake

How to work with promise with firestore + pdfmake in Firebase Functions


I'm trying to do a pdf file getting data from firestore using firebase functions, but now I'm getting a problem. I have this data structure:

  • Collection
    • Doc
      • Field1
      • Field 2
      • Another Collection
        • Doc
          • Field 2 ...
        • Doc 2 ...
    • Doc 2 ...

I need to convert this struture in a json to show on pdfMake. I know that I have to use promises, but the final object doesnt appear like I expect. When I use the first layer (only field from de firsts docs), works fine, but when I try to enter these same Doc's Collection, i receive a error. I'll put the code below.

The error is that my 'second then' return before than first "then" be resolved, so my PDF File render a blank file on the screen. It doesnt show any error, but on console I can see that data is fetched after the response be returned. I need to resolve the firsts then included on the loop before send any response, but it doesnt happen

exports.helloPDF = functions.https.onRequest( (request, response) => {
try {
    db.collection('lista_substituicao').get().then((lista_substituicao) =>{
        let docDefinition = { //definitions will be used on pdf file
            background: function () {
                return [
                    {
                    image: 'bg.jpg',
                    width: 550
                }
            ];
        },
        content: []
    };

    lista_substituicao.forEach( grupo => {
        let grupoDef = {id: grupo.id, ...grupo.data()}
        let tabelaGrupo = {
            table: {
                widths: ['*'],
                body: [
                    [`Grupo ${grupoDef.grupo}`]
                ]
            }
        } 

        db.collection(`lista_substituicao/${grupoDef.id}/alimentos/`).get().then(alimentos =>{
            let alimentosTable = {
                table: {
                    widths: ['*'],
                    body: [
                        ["Alimento"]
                    ]
                }
            }
            alimentos.forEach(alimentoDef =>{
                let alimento = {id: alimentoDef.id, ...alimentoDef.data()}
                alimentosTable['table']['body'].push([alimento.alimento])                    
            })

            tabelaGrupo['table']['body'].push(alimentosTable)
            docDefinition['content'].push(tabelaGrupo)
        })
    })

    return docDefinition

}).then((finalDocDefinition) =>{
    console.log(finalDocDefinition) // i get undefined here
    let doc = printer.createPdfKitDocument(docDefinition);
                response.setHeader('Content-Type', 'application/pdf');
                doc.end();
                return doc.pipe(response)
})


 } catch (error) {
    console.log(error)
}

})

Solution

  • I changed the code and now its working as expected.

    I did another functions whats return a json tree as I wanted. The code:

     db.collection(`lista_substituicao`).get().then(lista_substituicao =>{
        let grupos = []
        let grupoPromisses = []
    
        lista_substituicao.forEach(grupo => {
            let grupoData = {id: grupo.id, ...grupo.data(), alimentos: []}
            let promise = db.collection(`lista_substituicao/${grupo.id}/alimentos/`).get()
            grupoPromisses.push(promise)
            grupos[grupo.id] = grupoData
        })
    
        Promise.all(grupoPromisses).then(alimentos => {
            alimentos.forEach(alimentos =>{
                alimentos.forEach(alimento =>{
                    let idGrupo = alimento.ref.parent.parent.id
                    grupos[idGrupo]['alimentos'].push(alimento.data())
                })
            })
            return response.status(201).json({...grupos});
        })
    })