Olá k, até posso compartilhar mas o trecho nao fará sentido algum sem todo o contexto que ele se encontra, aqui está a parte que mensurei no post, foi por volta desse promise all:
await Promise.all(
proposals.map(async (proposal) => {
// Taxa
if (proposal.proposalTax.length) {
chargeIds.push({
pagarMeChargeId: proposal.proposalTax[0].pagarMeChargeId,
pagarMeUsed: proposal.proposalTax[0].pagarMeUsed,
})
}
// PropostaPayments
const proposalPayments = await ProposalPayments.query()
.preload('proposalBoletoParcelado')
.where('proposal_id', proposal.$attributes.id)
.andWhereNotNull('pagar_me_order_id')
if (proposalPayments && proposalPayments.length) {
await Promise.all(
proposalPayments.map(async (pp) => {
// Boleto Parcelado
if (pp.proposalBoletoParcelado && pp.proposalBoletoParcelado.length) {
await Promise.all(
pp.proposalBoletoParcelado.map((proposalBoletoParcelado) => {
chargeIds.push({
pagarMeChargeId: proposalBoletoParcelado.pagarMeChargeId,
pagarMeUsed: proposalBoletoParcelado.pagarMeUsed,
})
})
)
}
chargeIds.push({
pagarMeChargeId: pp.pagarMeChargeId!,
pagarMeUsed: proposal.pagarMeUsed,
})
})
)
}
// PropostaPayments
const proposalCardMemberships = await ProposalCardMemberships.query()
.preload('proposalCardCycles')
.where('proposal_id', proposal.$attributes.id)
if (proposalCardMemberships && proposalCardMemberships.length) {
await Promise.all(
proposalCardMemberships.map(async (pcm) => {
// Ciclos
if (pcm.proposalCardCycles && pcm.proposalCardCycles.length) {
await Promise.all(
pcm.proposalCardCycles.map((pcc) => {
if (!pcc.pagarMeChargeId) return
chargeIds.push({
pagarMeChargeId: pcc.pagarMeChargeId,
pagarMeUsed: pcm.pagarMeUsed,
})
})
)
}
})
)
}
})
)
Estou esperando um tempo livre para tentar reproduzi-lo e em breve posto aqui minhas conclusoes.
de cara no ultimo teste que fiz, tive resultados negativos quanto ao promisse.all()
.
import { createServer } from 'node:http'
import { performance } from 'node:perf_hooks'
const app = createServer()
app.on("request", async (_, response) => {
const casas = Array(100).fill({
pessoas: Array(100).fill({
bicicletas: Array(100).fill({
cor: ""
})
})
})
const map = () => {
let list = []
performance.mark("mapStart")
casas.map(casa => casa.pessoas.map(pessoa => pessoa.bicicletas.map(bicicleta => list.push(bicicleta.cor))))
performance.mark("mapEnd")
performance.measure("map", "mapStart", "mapEnd")
}
const forof = () => {
let list = []
performance.mark("forofStart")
for (const casa of casas) {
for (const pessoa of casa.pessoas) {
for (const bicicleta of pessoa.bicicletas) {
list.push(bicicleta.cor)
}
}
}
performance.mark("forofEnd")
performance.measure("forof", "forofStart", "forofEnd")
}
const all = async () => {
let list = []
performance.mark("allStart")
await Promise.all(
casas.map(async casa => {
await Promise.all(
casa.pessoas.map(async pessoa => {
await Promise.all(
pessoa.bicicletas.map(bicicleta => list.push(bicicleta.cor))
)
})
)
})
)
performance.mark("allEnd")
performance.measure("all", "allStart", "allEnd")
}
map()
forof()
await all()
console.log(performance.getEntriesByType("measure"))
response.end("ok")
})
app.listen(3333)
resultados:
[ PerformanceMeasure { name: 'map', entryType: 'measure', startTime: 3310.392207, duration: 33.59345100000019 }, PerformanceMeasure { name: 'forof', entryType: 'measure', startTime: 3344.32724, duration: 29.174007000000074 }, PerformanceMeasure { name: 'all', entryType: 'measure', startTime: 3373.629408, duration: 302.93898400000035 } ]
Bom, mudando um pouco de assunto, uma dica que posso dar é que - pelo menos no último exemplo - vc está não está usando map
da melhor maneira. Quer dizer, até "funciona", mas não é a ferramenta adequada para este caso.
A ideia do map
é executar algo com cada elemento de um array, e retornar outro array com os resultados. Ou seja, array.map(função)
executa a função para cada elemento do array, e cria outro array com os retornos desta função. Mas no seu caso vc está ignorando estes arrays retornados, que estão sendo criados à toa.
No fundo, vc está usando map
como um substituto do for
. E isso até "funciona", já que no fim ele vai percorrer por todos os elementos. Mas se vc não quer os resultados (os arrays que são criados cada vez que vc chama map
), então é um uso torto.
Vale lembrar que o resultado do map
é um array com o mesmo tamanho do array original, mas também não é isso que vc quer. Vc tem o array casas
com 100 elementos. Mas cada um desses elementos possui outro array, que por sua vez tem 100 elementos, sendo que cada um deles tem mais 100 elementos cada. E no fim o que te interessa é o array final com 1 milhão de elementos (os valores de todas as cores). Só o fato de resultar em um array com tamanho diferente do original já indica que map
não é o mais adequado.
Enfim, neste caso o ideal é usar for
mesmo. Inclusive, fiz uns testes usando o Benchmark.js e o for
foi bem mais rápido que o map
.
Quanto a usar Promise.all
, não faz sentido ali porque este método deve receber um array de promises. Mas vc está passando um array de arrays de arrays de números (sim, pois push
retorna o tamanho do array após a inserção do elemento, e depois este array é retornado para o map
de fora, que por sua vez repassa como um array de arrays para o map
mais externo). E segundo a documentação, os elementos que não são promises são ignorados. De qualquer forma, a demora talvez ocorra porque há um overhead em criar as promises - mas não muda o fato de não fazer sentido usar promises neste caso.
Quanto ao primeiro código, realmente fica difícil avaliar sem todo o contexto. Ainda sim eu acho estranho usar map
ali, pois no fundo parece que está fazendo array.map(e => outroArray.push(e))
- ou seja, está usando map
como um loop para preencher outro array, o que eu já disse que é um uso torto. E usar isso em conjunto com Promise.all
cai no que também citei acima, de passar coisas que não são promises, o que não faz sentido.
Enfim, eu revisaria esses pontos antes de tirar mais conclusões. Não sei nem se o uso de map
que deixou mais rápido, meu palpite é que não (mas claro, é apenas um chute sem conhecer todo o contexto).