Асинхронное извлечение в цикле - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть асинхронная операция, выбирающая массив элементов:

Base.find({ creatorId: req.params.id })

Каждый элемент в этом массиве имеет идентификатор, с помощью которого мне нужно выполнить выборку сообщений и пользователей для этого элемента. Для этого мне нужен цикл:

Base.find({ creatorId: req.params.id })
        .then(bases => {
            for (let base of bases) {
            }
        })

Bsae.find () вернет несколько элементов, следовательно, цикл. Конец метода GET в узле должен будет возвращать массив, который выглядит примерно так:

bases: [
  {
   base: {info about base},
   users: 12,
   messages: 51
   },
   ...another base...,
   ...another base...
]

До сих пор мне не удавалось включить в цикл несколько обещаний (методов .find), и я не смог serialize() получить информацию в последующем .then(). Я читал другие сообщения о переполнении стека, в которых они предлагали использовать функции async/await, но это позволило мне выполнить только один из двух методов (baseUser.find()). Я не знаю, как выполнить эти операции для каждой из баз, которые изначально возвращаются Base.find()

EDIT : Для уточнения мне нужно вызвать следующие функции: Base.find => возвращает массив баз. BaseUser.find() => который должен быть в цикле, потому что мне нужно find каждый элемент с Id из первого find. Message.find() => Так же, как baseuser, сообщения извлекаются с идентификатором от Base.find().

EDIT2 : Теперь я получаю некоторые данные, но в основном для меня бесполезно работать, так как я не знаю никакого способа получения данных из следующих источников:

async function fetcher() {
    try {
        const bases = await Base.find({ creatorId: req.params.id });
        const baseUserPromises = bases.map(base =>
            BaseUser.find({ baseId: base._id })
        );
        return await Promise.all(baseUserPromises);
    } catch (err) {
        console.error(err);
        res.status(500).json({ message: "Internal server error" });
    }
}
fetcher().then(data => console.log(data))

результат:

[ [ { created: 2018-09-03T14:05:39.968Z,
      acceptedMembership: true,
      isCreator: true,
      _id: 5b8d3fb3ccdfcc2e20540604,
      userId: 'tester1',
      baseId: 5b8d3fb3ccdfcc2e20540603},
    { created: 2018-09-03T14:05:43.357Z,
      acceptedMembership: false,
      isCreator: false,
      _id: 5b8d3fb7ccdfcc2e20540605,
      userId: 'tester2',
      baseId: 5b8d3fb3ccdfcc2e20540603},
    { created: 2018-09-03T14:05:44.797Z,
      acceptedMembership: false,
      isCreator: false,
      _id: 5b8d3fb8ccdfcc2e20540606,
      userId: 'tester3',
      baseId: 5b8d3fb3ccdfcc2e20540603 } ],
  [ { created: 2018-09-03T14:11:48.802Z,
      acceptedMembership: true,
      isCreator: true,
      _id: 5b8d4124e96ca00eb42df8c9,
      userId: 'tester1',
      baseId: 5b8d4124e96ca00eb42df8c8 } ] ]

Двойные массивы, поскольку Promise.all() возвращает первый массив с разрешенными Обещаниями, а затем Mongo collection.find() также возвращает массив. Таким образом, это массив Promise, заполненный двумя find массивами, заполненными результатами find

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Вы пробовали с Promise.all ?

 try {
    const bases = await Base.find({ creatorId: req.params.id });
    const baseUserPromises = bases.map(b => BaseUser.find({}));
    const result = await Promise.all(baseUserPromises);
  } catch (e) {
    // TODO: handle errors
  } finally {
    // DO: something
  }

Сначала получите все необходимые данные, а затем вы можете создать массив объектов, которые хотите вернуть.

EDIT Обновленный код

function getBasePromise(base) {
  return new Promise(async (resolve, reject) => {
    const users = await BaseUser.countDocuments({ baseId: base._id });
    resolve({
      base,
      users,
    });
  });  
}

async function fetcher() {
    try {
        const bases = await Base.find({ creatorId: req.params.id });
        const baseUserPromises = bases.map(base => getBasePromise(base));
        return await Promise.all(baseUserPromises);
    } catch (err) {
        console.error(err);
        res.status(500).json({ message: "Internal server error" });
    }
}
0 голосов
/ 03 сентября 2018

Согласно тому, что я понимаю из вашего вопроса, вы хотите получить базовый массив и использовать его для двух асинхронных функций. Вы можете сделать это следующим образом.

const sampleFunc = async function(){
  try {
    const bases = await Base.find(YOUR_REQUIREMENT);
    const baseUsers = await BaseUser.find(YOUR_REQUIREMENT);
    const messages = await Message.find(YOUR_REQUIREMENT);
  } catch (error) {
    console.log(error);
  }
}

Этот метод должен работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...