노드js-Paralelismo limitado com 배열.지도.
19631 단어 ptbrnodewebdevjavascript
OArray.map ()èuma funçO muitoútil,mas,infelizmente,sófunciona com funçes síncronas.Uma Solu231;o simples para executar funçes
async
éusar oPromose.all()
ou seu irmão mais tolerantePromise.allSettled()
:// Falha no momento que UMA função do .map falhar
const results = await Promise.all(array.map(asynMapFunction))
// Continua executando mesmo se uma função falhar
const results = await Promise.allSettled(array.map(asynMapFunction))
함수 aassim:o.map()
iráconvertercada item do array emuma Promise,então teremosum array de Promises para resolver.Háduas maneiras de fazer isso:Promise.all()
:joga um erro se a funão no.지도jogarumerro(MDNPromise.allSettled()
: funöes no로 실행합니다.맵emtodoo 진열, mesmoque algumas delas joguemumerro(MDN.allSettled()
éum array de objetos que informa se a execuão falhou ou não.Cada objeto na saída de
.allSettled()
éparecido com este:// Quando a função roda com sucesso
{
status: "fulfilled",
value: // o valor retornado da função do .map
}
// Quando a função joga um erro
{
status: "rejected",
reason: // o erro jogado pela função do .map
}
Porém, háum problema: ao contr á rio de um.map()
'정상'입니다. 왜냐하면 fun ões de mapan ão ser ão executadas em série 때문입니다.funöesasync
로mapaestarãoexecutandoaomesmotempo를 합니다.Embora o JavaScript seja normalmente uma linguagem de threadúnica,isso signific que os recursos alocados(como memória e portas)para cada funão serão ocupados atéque as Promises sejam resolvidas ou rejeitadas.Para array enormes,no entanto,vamos executar um grande numero de funões mapa ao mesmo tempo.Isso pode Potentialmente:eachLimit
do popular módulo async
.너는 우리의 생활이 간단하다고 생각하니?Vamos 실험 e aprender 알고리즘.Limitar chamadas paralelas 회사
로고 de cara,vamos usar 발전기.Sei queum recurso do JavaScript que muitos desenvolvedores(유럽연합 포함) n ãusam com frequeuência,mas neste caso,isso reduzir á uso de memó ria e criar á digo mais limpo.
범례
Vamos definir um problema hipotético primeiro.Temos 100 URL que queremos buscar,mas não queremos mais do que 10 chamadas paralelas ao mesmo tempo.Vamos usar o Google porque eles geralmente conseguem lidar com esse tipo de carga com facilidade!
// O array de URLs que queremos buscar
const urls = []
for (let i = 0; i < 100; i++) {
// O parâmetro de pesquisa 'q' é o número do índice
urls.push(`https://www.google.com/search?q=${i}`)
}
// A requisição é feita em uma função map assíncrona
async function mapFn(url, i) {
// Estamos usando https://www.npmjs.com/package/got
const contents = await got(url)
return { i, url, contents }
}
Agora vamos escrever um programa que pegue essas 100 URL,e as mapeia para imprimar os resultados:async function main() {
const results = await mapAllSettled(urls, mapFn, 10)
console.dir(results)
}
// Rodando a função "async main()" usando https://www.npmjs.com/package/am
am(main)
Agora precisamos escrever a funãomapAllSettled()
queébem semelhante a,Promise.allSettled(array.map(asyncMapFn))
,mas com um limite.Sua assinatura se parece com isso:async function mapAllSettled(array, mapFn, limit)
.Mas vamos voltar um pouco e ver como ser á essa execu ã o. Para simplificar, digamos que temos 10개 URL.Se fossemos buscar todas elas de uma vez,teríamos algo assim:
Mas se tivéssemos um limite de quatro buscas ao mesmo tempo,seria assim:
Assim que uma busca for concluda,prosseguiremos com a próxima.카다웨이스라는 사람, 테모스 콰트로 부스카 엠 앤더멘토라는 사람.Vamos regorganizar o tempo de execuão em quatro linhas que serão executadas por alguns“trabalhadores”:
Todos os trabalhadores“consomem”o mesmo array,mas“inserem”o resultado na posião correta no array resultant,de forma que o valor mapeado para a URL número sete termine na posião sete do array resultate.
Éaquique os geradores sãoúteis.Podemos definir um gerador que recebe um array e
yield
o quea função de mapa espera:function* arrayGenerator(array) {
for (let index = 0; index < array.length; index++) {
const currentValue = array[index]
yield [ currentValue, index, array ]
}
}
Para manter o formato de saída consistente com oPromise.allSettled()
,podemos executar as funões do mapa em um blocotry..catch
e emitter o resultado em um objeto com o formato:async function mapItem(mapFn, currentValue, index, array) {
try {
return {
status: 'fulfilled',
value: await mapFn(currentValue, index, array)
}
} catch (reason) {
return {
status: 'rejected',
reason
}
}
}
Cada trabalhador usa a funão do gerador para buscar ocurrentItem
,index
e uma referência aoarray
,então chamamosmapItem()
para executar omapFn()
assíncrono:async function worker(id, gen, mapFn, result) {
for (let [ currentValue, index, array ] of gen) {
console.time(`Worker ${id} --- index ${index} item ${currentValue}`)
result[index] = await mapItem(mapFn, currentValue, index, array)
console.timeEnd(`Worker ${id} --- index ${index} item ${currentValue}`)
}
}
Eu adicionei algunsconsole.time()
econsole.timeEnd()
para tornar a saída mais compreensível,mas,basicamente,essa funão tem duas linhas de código:for..of
consome dados do geradormapItem()
chama a funão specificada pelo usuáriomapFn()
e returna seus resultados em um objeto que tem o mesmo formato quePromise.allSettled()
mapAllSettled()
que basicamente cria esses trabalhadores e espera que eles terminem,depos returna os resultados:async function mapAllSettled(arr, mapFn, limit = arr.length) {
const result = []
if (arr.length === 0) {
return result
}
const gen = arrayGenerator(arr)
limit = Math.min(limit, arr.length)
const workers = new Array(limit)
for (let i = 0; i < limit; i++) {
workers.push(worker(i, gen, mapFn, result))
}
await Promise.all(workers)
return result
}
A chave aquiécompatilhar o gerador(gen
)entre os trabalhadores.Obviamente,não hásenido em processar se o array estiver vazio,então tiramos esse caso extremo da linha quatro.Além disso,não faz sentido ter mais trabalhadores do que elementos do array,portanto,na linha 10,garantimos quelimit
éno máximo igual ao comprimento da matriz.결론
Olimit
padrãO comprimento do array,O que faz com quemapAllSettled()
se comporte exatamente comoPromise.allSettled()
porque todas as funões do mapa serãO executadas em paralelo.Mas o objetivo dessa funão dar aos usuários o controle para definir um número menor de paralelismo.
O código completo estáno Githubse vocêquiser brincar com ele(licença MIT).
Obrigado pela leitura.Se vocêtiver comentários ou perguntas,entre em contato no.
Créditos 회사
async map with limited parallelism in Node.js,escrito originalmente por.
Reference
이 문제에 관하여(노드js-Paralelismo limitado com 배열.지도.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/oieduardorabelo/node-js-paralelismo-limitado-com-array-map-55ml텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)