首页 > 解决方案 > 对 json 数据使用异步的最佳实践

问题描述

我正在尝试将接收到的数据保存为数据库中的 JSON。但是我的方法不必要地耗时,所以我写了这个问题。

这是我的代码:

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();

结果是:

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 应该等待 createUser 在启动之前退出。但无需等待 data[0] 完成即可保存 data[1]。如何并行运行它们?

标签: javascriptasynchronousasync-await

解决方案



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;
}

推荐阅读