Estoy tratando de guardar los datos recibidos como JSON en DB. Pero mi método consume innecesariamente mucho tiempo, así que escribo la pregunta.
Aquí está mi código:
const data = [{ id: 1, name: 'foo', items: [{ name: 'foo-1' }, { name: 'foo-2' }] }, { id: 2, name: 'bar', items: [{ name: 'bar-1' }, { name: 'bar-2' }] }] const createUser = (data) => { console.log('start create user:', data) return new Promise(resolve => { setTimeout(() => { console.log('create user: ', data.name) resolve(data.id); }, 2000); }); } const createUserMeta = (id, name) => { console.log('start create user meta:', name) return new Promise(resolve => { setTimeout(() => { console.log('create user meta: ', id, name) resolve(`set ${id}: ${name}`) }, 3000) }) } // Logic async function asyncCall() { const result = [] console.log('calling') for (const i of data) { console.log(i) const usersId = await createUser(i) for (const item of i.items) { const fn2Return = await createUserMeta(usersId, item.name) result.push(fn2Return) } } console.log(result) } asyncCall();el resultado es:
calling { id: 1, name: 'foo', items: [ { name: 'foo-1' }, { name: 'foo-2' } ] } start create user: { id: 1, name: 'foo', items: [ { name: 'foo-1' }, { name: 'foo-2' } ] } // wait 2 sec create user: foo start create user meta: foo-1 // wait 3 sec create user meta: 1 foo-1 start create user meta: foo-2 // wait 3 sec create user meta: 1 foo-2 { id: 2, name: 'bar', items: [ { name: 'bar-1' }, { name: 'bar-2' } ] } start create user: { id: 2, name: 'bar', items: [ { name: 'bar-1' }, { name: 'bar-2' } ] } // wait 2 sec create user: bar start create user meta: bar-1 // wait 3 sec create user meta: 2 bar-1 start create user meta: bar-2 // wait 3 sec create user meta: 2 bar-2 [ 'set 1: foo-1', 'set 1: foo-2', 'set 2: bar-1', 'set 2: bar-2' ]createUserMeta debe esperar a que se cierre createUser antes de iniciarlo. Pero no es necesario esperar a que se completen los datos[0] para guardar los datos[1]. ¿Cómo puedo ejecutarlos en paralelo?
Envuelva la creación del usuario y los metadatos relacionados con una función como
async function createUserAndMeta(user) { console.log(user); const usersId = await createUser(user); const result = []; for (const item of user.items) { const fn2Return = await createUserMeta(usersId, item.name); result.push(fn2Return); } return result; } y luego use map para asignar a todos los usuarios a las promesas y Promise.all() para esperarlas:
async function asyncCall() { const results = await Promise.all(data.map(createUserAndMeta)); const result = results.flat(); // flatten array of arrays console.log(result); } Tenga en cuenta que si tiene una gran cantidad de data , esto hará que todas las solicitudes se realicen en paralelo (por ejemplo, para 50 usuarios, intentará realizar 50 llamadas paralelas a createUser ). Para limitar la concurrencia a, por ejemplo, 5 a la vez, es posible que desee utilizar, por ejemplo, el módulo p-queue .
async function createUser(data) { const pk = await insertUser(data.id, data.name); const result = await Promise.all(data.items.map(createUserMeta); return {pk, result}; } async function asyncCall() { const result = await Promise.all(data.map(createUser)); return result; }