代码之家  ›  专栏  ›  技术社区  ›  Markus

无法理解异步/等待节点

  •  0
  • Markus  · 技术社区  · 6 年前

    好的,所以我很难理解异步/等待、承诺等是如何工作的。在nodejs中,这是我第一次用异步语言编程。

    我在这里要做的基本上是从mongoose模型“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 回复  |  直到 6 年前
        1
  •  1
  •   Bergi    6 年前

    使用时不要使用回调 async / await (当使用简单的承诺时,使用 只有 then 回调)。你也不应该使用 等候 关于你仍然需要作为承诺对象的承诺,将其传递给 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 在结果数组中的对象上,您还可以直接转换承诺(类似于您使用 等候 ):

    promises.push(SecSolution.findOne().skip(random).lean().then(card => card._id));
    
        2
  •  0
  •   Prince Hernandez    6 年前

    基本上你必须认为它会尝试运行所有的东西,所有需要等待解决的代码不会停止运行所有代码的过程。

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

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

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

    3) 打印 debug 消息

    4) 退货 未定义 因为交换机内部的等待未解决。

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