Проблемы с пониманием async / await nodejs - PullRequest
0 голосов
/ 02 мая 2018

Хорошо, у меня возникли проблемы с пониманием того, как работают асинхронные / ожидающие, обещания и т. Д. В nodejs, это мое первое программирование на асинхронном языке.

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

async function getRandomCardIds(deckIdentifier, cardCount) {
    let arr;
    switch (deckIdentifier) {
        case 102:
            await SecSolution.count().exec(async function (err, count) {
                let promises = [];
                var random = Math.floor(Math.random() * count);
                for (let i = 0; i < 2; i++) {
                    promises.push((await SecSolution.findOne().skip(random).lean())._id);
                }
                arr = await Promise.all(promises);
                debug("This gets printed second" + arr);
            });
            break;
    }
    debug("this gets printed first");
    return arr;
}

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

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

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

1) определите arr как undefined и войдите в коммутатор.

2) в операторе switch у нас есть await, поэтому он будет ждать (но не остановит выполнение другого кода, потому что он не принадлежит тому же оператору), он разрешится позже.

3) печатает сообщение debug

4) возвращает undefined, поскольку ожидание внутри коммутатора не разрешено.

5) однажды утверждение будет решено, но вы ничего не можете с этим поделать.

Примером может быть следующий.

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

asyncCall();

так что вы можете сделать в вашем случае следующее:

function resolveInnerFunct() {
  return new Promise(resolve => {
    let promises = [];
    var random = Math.floor(Math.random() * count);
    for (let i = 0; i < 2; i++) {
      promises.push(SecSolution.findOne().skip(random).lean())._id));
    }
    Promise.all(promises).then(values=> {return resolve(values)};
  });
}

async function asyncCall() {
  console.log('calling');
  let arr;
  switch (deckIdentifier) {
    case 102:
      // this will wait until the resolveInnerFunct resolves.
      arr = await resolveInnerFunct();
      debug("this wont get printed before the other message")
      break;
  }
  debug("this gets printed first");
  return arr;
}

asyncCall();
0 голосов
/ 02 мая 2018

Не используйте обратные вызовы при работе с async / await. (А при работе с простыми обещаниями используйте только then обратные вызовы). Также вы не должны использовать await для обещания, которое вам все еще нужно в качестве объекта обещания, чтобы передать его Promise.all. Ваш код должен быть

async function getRandomCardIds(deckIdentifier, cardCount) {
    switch (deckIdentifier) {
        case 102:
            const count = await SecSolution.count(); // a promise(like object)
            let promises = [];
            var random = Math.floor(Math.random() * count);
            for (let i = 0; i < 2; i++) {
                promises.push(SecSolution.findOne().skip(random).lean());
            }
            let arr = await Promise.all(promises);
            debug("This gets printed second" + arr);
            return [arr[0]._id, arr[1]._id];
            break;
    }
    debug("this gets printed first");
    return undefined;
}

Вместо доступа к _id s для объектов в массиве результатов, вы также могли бы напрямую преобразовать обещания (аналогично тому, что вы пробовали с await):

promises.push(SecSolution.findOne().skip(random).lean().then(card => card._id));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...