如果没有在Promise中显式包装返回值,是不是异步返回Promise?

时间:2018-02-05 20:10:49

标签: javascript async-await ecmascript-2017

MDN documentation声明

  

当调用异步函数时,它返回一个Promise。当异步时   函数返回一个值,Promise将被解析   返回值。当异步函数抛出异常或某些异常时   价值,承诺将以抛出的价值被拒绝。

因此,考虑到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()函数返回undefined。尽管如此,我认为通过单独调用async函数本身会使函数立即返回一个未解析的promise,并且当async函数返回时这样的promise将得到解决任何值(甚至未定义)。但我现在意识到,真的需要通过return Promise语句声明它来回复自己的承诺。我认为我所读到的async的MDN文章在这个主题上有点令人困惑(仅仅是我的意见)。

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

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

1 个答案:

答案 0 :(得分:3)

bar()正在设置超时并返回undefined,这与立即运行超时结束时运行的日志语句不同。

因此,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");    
}




最终代码段 等待承诺的解决,因此您会看到bar,然后foo

以上delay取自https://stackoverflow.com/a/39538518/3084820

这是最后一个例子,bar()返回" bar"。这意味着它会被async声明包含在承诺中,并由await内部foo()解决。再次,您会看到您希望看到的内容。



foo();

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

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

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




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

  1. 立即返回的承诺表单bar(),解析为undefined
  2. 来自zoo函数的值zoo()
  3. 最后,经过1000毫秒后,您会看到从bar中记录的setTimeout已被推入队列。
  4. 试一试,看看你得到了什么。