JS Карта массива возвращается пустой - PullRequest
0 голосов
/ 20 апреля 2020

Я пытаюсь использовать карту, чтобы вернуть новое поле в массиве объектов, и как только я это сделаю, он возвращает пустое.

Ожидаемый результат:

[
    {
        "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);

Что я могу сделать, чтобы все заработало как положено?

Ответы [ 3 ]

0 голосов
/ 20 апреля 2020

async функции всегда возвращают Promise, но .map не «ожидает» этих обещаний (они просто помещают их «как есть» в результате). Если вы хотите получить все результаты, самый простой способ будет Promise.all:

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

Примечание: при этом все операции начнутся параллельно (одновременно) и будут ждать все они должны быть решены, прежде чем продолжить. Если venues - это очень большой массив, это может привести к большому количеству соединений с вашей базой данных и потенциально вызвать некоторые проблемы.

Чтобы выполнять запросы один за другим, вам потребуется l oop и ждите, пока предыдущий будет решен. Один из способов сделать это можно сделать, используя 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([]));
0 голосов
/ 20 апреля 2020

venues.map вернет массив Обещаний. Обещания не преобразуются в JSON - ну, они делают, до {}

Итак, вы должны дождаться всех обещаний, возвращаемых .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);
0 голосов
/ 20 апреля 2020

Вам нужно использовать Promise.All в вашем коде.

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