无法理解 async/await nodejs

Posted

技术标签:

【中文标题】无法理解 async/await nodejs【英文标题】:Trouble understanding 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 不应该在循环内吗? 是的,你是对的,还没有注意到,因为它没有返回任何东西:) 【参考方案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();

【讨论】:

以上是关于无法理解 async/await nodejs的主要内容,如果未能解决你的问题,请参考以下文章

kestrel vs async await c#

前端_js理解 JavaScript 的 async/await

简单理解JavaScript 的async/await

理解 async/await

理解 JavaScript 的 async/await

对python async与await的理解