Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Aguardar Promise dentro de um map

Tenho o seguinte codigo:

const Conexao = require('../../infra/conexao/conexao')
const Consulta = require('../../infra/administrador/consultas')
const Departamento = require('../../infra/consultas/departamentos')

module.exports = (app) => {

    app.get('/consulta-niveis', (req, res) => {

        res.marko(require('../../views/administrador/administrador.marko'))
    })

    app.get('/niveis-adm', (req, res) => {

        new Conexao().base().then(conexao => {

            let estrutura = async function () {

                let trabalho = await Departamento.nivel1(conexao).then(resultado => {

                    let result = resultado.rows.map(n1 => {

                        return `
                            <div class="alinha">

                                <button class="clicar"></button><span>${n1}</span>

                                ${(async function () {

                                    await Departamento.nivel2(conexao, 18, n1).then(async resultado => {

                                        return Promise.all(resultado.rows.map(async n2 => {

                                            return (async () => `
                                                <div class="alinha">
                                                    <button class="clicar"></button><span>${n2}</span>

                                                    ${(async function () {

                                                    let trabalho = await Departamento.nivel3(conexao, 18, n1, n2).then(resultado => {

                                                        let result = resultado.rows.map(n3 => {

                                                            return `

                                                                <div>
                                                                    <button class="clicar"></button><span>${n3}</span>
                                                                </div>
                                                            `
                                                        })
                                                        return result
                                                    })

                                                    return trabalho.join('')
                                                })()}
                                                </div>
                                            `)()
                                        }))
                                    })

                                    return trabalho
                                })()}

                            </div>
                        `
                    })

                    return result
                })

                return trabalho.join('')

            }

            estrutura().then(dados => {

                console.log(dados);
            })
        })
    })
}

Que me retorna isto:

<div class="alinha">

    <button class="clicar"></button><span>MERCEARIA</span>

    [object Promise]

</div>

<div class="alinha">

    <button class="clicar"></button><span>PERECIVEIS</span>

    [object Promise]

</div>

<div class="alinha">

    <button class="clicar"></button><span>NAO ALIMENTAR</span>

    [object Promise]

</div>

Esta minha conexao comunica com o banco oracle que realiza uma consulta assíncrona, isto me retorna um array que é iterado no map que realiza mais uma consulta assincrona, como faço para aguardar dentro do map todas as consultas serem feitas, e só entao devolver a string completa?

4 respostas
solução!

Fala ai Felix, tudo bem? Você pode fazer um async/await dentro de cada item no seu map e no final realizar um Promise.all dele, algo assim:

Promise.all(itens.map(async item => {
    await fazAlgo(item)
})

Espero ter ajudado,

Utilizando o Promisse.all junto com um await na IIFE resolveu. O cdg ficou o seguinte:

new Conexao().base().then(async conexao => {

    let dados = await Departamento.nivel1(conexao).then(async resultado => {

        let dados = resultado.rows.map(async n1 => {

            return `

                <div class="alinha">

                    <input type="checkbox" name="${n1}" id="n1" value="${n1}" class="marcador"/>
                    <button class="clicar"></button>
                    <label for="n1">${n1}</label>
                    <div class="contexto">
                    ${await (async ()  => {

                        let dados = await Departamento.nivel2(conexao, n1[0]).then(async resultado => {

                            let dados = resultado.rows.map(async n2 => {

                                return `

                                    <div class="alinha" style="display: none;">
                                        <input type="checkbox" name="${n2}" id="n2" value="${n2}" class="marcador"/>
                                        <button class="clicar"></button>
                                        <label for="n2">${n2}</label>
                                        <div class="contexto">
                                        ${await (async () => {

                                            let dados = await Departamento.nivel3(conexao, n1[0], n2[0]).then(async resultado => {

                                                let dados = resultado.rows.map(async n3 => {

                                                    return `

                                                        <div class="alinha">

                                                            <input type="checkbox" name="${n3}" id="n3" value="${n3}" class="marcador"/>
                                                            <button class="clicar"></button>
                                                            <label for="n3">${n3}</label>

                                                        </div>

                                                    `
                                                })

                                                let result = await Promise.all(dados).then(result => {

                                                    return result
                                                })

                                                return result
                                            })

                                            return dados

                                        })().then(dados => {

                                            return dados.join('')
                                        })}

                                        </div>

                                    </div>

                                `
                            })

                            let result = await Promise.all(dados).then(result => {

                                return result
                            })

                            return result
                        }).then(dados => {

                            return dados.join('')
                        })

                        return dados
                    })().then(dados => {

                        return dados
                    })}
                    </div>

                </div>

            `
        })

        let result = await Promise.all(dados).then(result => {

            conexao.close()
            return result
        })

        return result
    })

    res.send(dados)
})

Porem esta não foi a melhor solução o código ficou extremamente lento pois havia muitos registros, para montar este html foi gerada mais de 1500 consultas ficou inviável. No proximo post mostrarei a solução com melhorias no desempenho.

Neste caso utilizo apenas um SQL que me retorna todos os dados de uma unica vez em um array para isso itero as colunas retornando funções comuns sem consultas dentro do template string, desta forma:

function montaHtml (dados) {

    let n1 = []
    let n2 = []
    let n3 = []
    let n4 = []
    let html = []

    dados.forEach(item => {

        if(n1.indexOf(item[0]) == -1) {

            n1.push(item[0])
            html.push(`

                <div class="alinha">

                    <input type="checkbox" name="${item[0]}" id="n1" value="${item[0]}" class="marcador"/>

                        <button class="clicarN1"></button>

                    <label class="n1">${item[4]}</label>

                    <div class="contexto">

                        ${(() => {

                            let htmlN2 = []
                            dados.forEach(itemN2 => {


                                if(n2.indexOf(itemN2[1]) == -1 && itemN2[0] == item[0]) {

                                    n2.push(itemN2[1])

                                    htmlN2.push(`

                                        <div class="alinhaN2" style="display: none;">

                                            <input type="checkbox" name="${itemN2[1]}" id="n2" value="${itemN2[1]}" class="marcador"/>
                                                <button class="clicarN2"></button>
                                            <label class="n2">${itemN2[5]}</label>

                                            <div class="contexto">

                                                ${(() => {

                                                    let htmlN3 = []
                                                    dados.forEach(itemN3 => {

                                                        if(n3.indexOf(itemN3[2]) == -1 && itemN3[0] == item[0] && itemN3[1] == itemN2[1]) {

                                                            n3.push(itemN3[2])

                                                            htmlN3.push(
                                                                `
                                                                <div class="alinhaN3" style="display: none;">

                                                                    <input type="checkbox" name="${itemN3[2]}" id="n3" value="${itemN3[2]}" class="marcador"/>
                                                                        <button class="clicarN3"></button>
                                                                    <label class="n3">${itemN3[6]}</label>

                                                                </div>
                                                                `
                                                            )
                                                        }
                                                    })

                                                    return htmlN3
                                                })().join('')}

                                            </div>
                                        </div>
                                    `)
                                }
                            })
                            return htmlN2
                        })().join('')}
                    </div>
                </div>
            `)
        }
    })
    return html.join('')
}

Boa Felix, fico feliz que tenha dado certo, sempre que precisar não deixe de criar suas dúvidas.

Abraços e bons estudos.