JS数组映射返回空

JS Array map returning empty

我正在尝试使用映射到 return 对象数组中的一个新字段,一旦我这样做 return 就空了。

预期结果:

[
    {
        "id": 2,
        "name": "awesome stadium",
        "opened": "1970-01-01T00:00:00.000Z",
        "capacity": "39590.00",
        "location": "some awesome",
        "team_id": "147ff48e",
        "team": {
            "name": "some name",
            "location": "some location"
        }
    }
]

代码:

    const venues = await connection(VENUE_TABLE)
      .limit(LIMIT_PER_PAGE)
      .offset((page - 1) * LIMIT_PER_PAGE)
      .select('*');

    const venuesWithTeam = venues.map(async (element) => ({
      ...element,
      team: await connection('team')
        .where('id', element.team_id)
        .select('*')
        .first(),
    }));

    return response.json(venuesWithTeam);

我该怎么做才能让它按预期工作?

您需要在代码中使用 Promise.All

const venuesWithTeam = await Promise.all(venues.map(async (element) => ({
  ...element,
  team: await connection('team')
    .where('id', element.team_id)
    .select('*')
    .first(),
})));

async 总是 return 一个 Promise,但是 .map 不会 "await" 这些 promise(它只是将它们 "as is" 放在结果中)。如果你想获得所有结果,最简单的方法是 Promise.all:

const venuesWithTeam = await Promise.all(venues.map(async (element) => ({
  ...element,
  team: await connection('team')
    .where('id', element.team_id)
    .select('*')
    .first(),
})));

注意:这将开始 运行并行(同时)执行所有操作,并等待所有操作都解决后再继续。如果 venues 是一个非常大的数组,它可能会导致大量连接到您的数据库并可能导致一些问题。

到运行一个接一个的请求,你将不得不循环等待前一个被解决。一种方法是使用 reduce.

const venuesWithTeam = await venues.reduce((prom, element) => (
  prom.then(async result => (
    result.concat({
      ...element,
      team: await connection('team')
        .where('id', element.team_id)
        .select('*')
        .first(),
    })
  ))
), Promise.resolve([]));

venues.map 将 return 一个 Promise 数组。 Promise 不会字符串化为 JSON - 好吧,它们会字符串化为 {}

因此,您必须在代码中等待 return由 .map 编辑的所有承诺

所以,Promise.all(x.map( ..... ))

const venuesWithTeam = await Promise.all(venues.map(async(element) => ({
  ...element,
  team: await connection('team')
    .where('id', element.team_id)
    .select('*')
    .first(),
})));

return response.json(venuesWithTeam);

或者,运行 每次迭代都是串联的而不是并行的

const venuesWithTeam = [];
for (element of venues) {
  venuesWithTeam.push({
    ...element,
    team: await connection('team')
      .where('id', element.team_id)
      .select('*')
      .first(),
  });
}
return response.json(venuesWithTeam);