【问题标题】:Trouble understanding async/await nodejs无法理解 async/await nodejs
【发布时间】:2018-10-13 00:14:59
【问题描述】:

好吧,我在理解 nodejs 中的 async/await、Promises 等如何工作时遇到了麻烦,这是我第一次使用异步语言进行编程。

我在这里尝试做的基本上是从猫鼬模型“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;
}

提前致谢!

【问题讨论】:

  • 你确定random 不应该在循环内吗?
  • 是的,你是对的,还没有注意到,因为它没有返回任何东西:)

标签: javascript node.js asynchronous mongoose promise


【解决方案1】:

在使用 async/await 时不要使用回调。 (当使用简单的 Promise 时,only then 回调)。此外,您不应在仍需要作为 Promise 对象的 Promise 上使用 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;
}

除了访问结果数组中对象的_ids,您还可以直接转换promise(类似于您尝试使用await):

promises.push(SecSolution.findOne().skip(random).lean().then(card => card._id));

【讨论】:

  • 只是另一个简单的问题,因为我喜欢像你说的那样直接转换承诺的巧妙技巧:promises.push(SecSolution.findOne().skip(random).lean().then(card =&gt; card._id));我如何使用 find() 而不是 findOne() 来完成这个?
【解决方案2】:

嗯,基本上你必须认为它会尝试运行所有内容,并且所有需要等待解析的代码不会停止运行所有代码的过程。

因此,查看您的代码,我们可以看到以下内容:

1) 将arr 定义为undefined 然后进入开关内部。

2) 在 switch 语句中我们有一个await,所以它会等待(但它不会停止其他代码的运行,因为它不在同一个语句上),它会在稍后解决。

3) 打印debug 消息

4) 返回undefined,因为 switch 内部的 await 没有解析。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 2018-04-12
    • 2020-03-25
    • 1970-01-01
    • 2020-05-02
    • 2017-11-14
    相关资源
    最近更新 更多