不应该在 Promise 中显式包装 return 值的情况下异步 return Promise 吗?

Shouldn't async return a Promise without explicitly wrapping the return value in a Promise?

MDN documentation 指出

When an async function is called, it returns a Promise. When the async function returns a value, the Promise will be resolved with the returned value. When the async function throws an exception or some value, the Promise will be rejected with the thrown value.

因此,考虑到 await 期望得到解决的承诺,我做错了什么?

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
    setTimeout(() => {
        console.log("bar");
        return;
    }, 1000);    
}

function zoo(){
    console.log("zoo");    
}

根据我(错误)的理解,它应该首先记录 bar 然后 zoo,但它以相反的方式记录。

编辑: 现在,感谢@Matt Morgan 的澄清,我明白了这个错误,因为 bar() 函数 returns undefined.尽管如此,我认为通过单独调用 async 函数 本身 会使函数 return 立即成为未解决的承诺,并且当 async 函数会 return 任何值(甚至未定义)。但我现在意识到一个人确实需要 return 通过用 return Promise 语句声明它自己的承诺。我认为 async 的 MDN 文章在这个主题上有点令人困惑(只是我的意见),我通读了所有内容。

因此我可以简单地将 bar() 函数修改为:

function bar(){
    return new Promise(function(resolve){
        setTimeout(() => {
            console.log("bar");
            resolve();
        }, 1000);
    });
}

bar() 正在设置超时并 return 未定义,这与立即 运行 超时完成时运行的日志记录语句不同。

因此,zoo() 运行,然后当超时结束时(1000 毫秒后),您会在控制台中看到 "bar"。

这是一个修改后的例子没有超时:

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
   console.log("bar");   
}

function zoo(){
    console.log("zoo");    
}

如果没有 setTimeout,您将获得您期望的执行顺序。

第二个例子,你有一个 delay() 函数将 setTimeout 包装在一个承诺中:

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
   await delay();
   console.log("bar");   
}

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

function zoo(){
    console.log("zoo");    
}

最后的代码段 等待 promise 的解析,因此您会看到 bar,然后 foo

以上delay摘自

这是最后一个示例,其中 bar() returns "bar"。这意味着它被 async 声明包裹在一个承诺中,并由 foo() 内部的 await 解析。再次,你看到你期望看到的。

foo();

async function foo(){
    console.log(await bar());
    zoo();
}

async function bar(){
    return 'bar';   
}

function zoo(){
    console.log("zoo");    
}

了解您的原始示例 不 return 值 bar 很重要。它 returns undefined,如果您更改原始代码以注销 bar() 的 returned 值,您将在控制台中看到三件事:

  1. 立即 returned 承诺形式 bar() 解析为 undefined
  2. 来自 zoo() 函数的值 zoo
  3. 最后,在 1000 毫秒过去后,您会看到从 setTimeout 中记录的 bar 被推到队列中。

试试吧,看看你会得到什么。