async/await 隐式返回 promise?

我读到由关键字标记的异步函数隐式返回一个 promise:async

async function getVal(){
 return await doSomethingAync();
}

var ret = getVal();
console.log(ret);

但这是不连贯的...假设返回一个 promise,并且 await 关键字将返回 promise 中的值,而不是 promise itsef,那么我的 getVal 函数应该返回该值,而不是隐式 promise。doSomethingAsync()

那么究竟是什么情况呢?由 async 关键字标记的函数是隐式返回 promise,还是我们控制它们返回的内容?

也许如果我们没有明确地返回某些东西,那么他们隐含地返回一个承诺......?

更清楚的是,上述和

function doSomethingAync(charlie) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(charlie || 'yikes');
        }, 100);
    })
}

async function getVal(){
   var val = await doSomethingAync();  // val is not a promise
   console.log(val); // logs 'yikes' or whatever
   return val;  // but this returns a promise
}

var ret = getVal();
console.log(ret);  //logs a promise

在我的概要中,这种行为确实与传统的返回语句不一致。看起来,当您从函数显式返回非 promise 值时,它将强制将其包装在 promise 中。我没有大问题,但它确实违背了正常的JS。async


答案 1

返回值将始终是一个承诺。如果未显式返回 promise,则返回的值将自动包装在 promise 中。

async function increment(num) {
  return num + 1;
}

// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));

即使没有回报,也是一样的!( 返回)Promise { undefined }

async function increment(num) {}

即使有.await

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function incrementTwice(num) {
  const numPlus1 = await defer(() => num + 1);
  return numPlus1 + 1;
}

// Logs: 5
incrementTwice(3).then(num => console.log(num));

Promise 自动展开,因此,如果您确实从函数中返回值的 promise,您将收到值的承诺(而不是值的承诺)。async

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function increment(num) {
  // It doesn't matter whether you put an `await` here.
  return defer(() => num + 1);
}

// Logs: 4
increment(3).then(num => console.log(num));

在我的概要中,这种行为确实与传统的返回语句不一致。看起来,当您从异步函数显式返回非 promise 值时,它会强制将其包装在 promise 中。我没有大问题,但它确实违背了正常的JS。

ES6 具有不返回与 . 完全相同的值的函数。这些函数称为生成器。return

function* foo() {
  return 'test';
}

// Logs an object.
console.log(foo());

// Logs 'test'.
console.log(foo().next().value);

答案 2

我看了一下规格,发现了以下信息。简短的版本是将脱硫糖器送到产生s的发电机上。所以,是的,异步函数返回承诺async functionPromise

根据 tc39 规范,以下情况属实:

async function <name>?<argumentlist><body>

脱硫醋到:

function <name>?<argumentlist>{ return spawn(function*() <body>, this); }

其中“是对以下算法的调用”:spawn

function spawn(genF, self) {
    return new Promise(function(resolve, reject) {
        var gen = genF.call(self);
        function step(nextF) {
            var next;
            try {
                next = nextF();
            } catch(e) {
                // finished with failure, reject the promise
                reject(e);
                return;
            }
            if(next.done) {
                // finished with success, resolve the promise
                resolve(next.value);
                return;
            }
            // not finished, chain off the yielded promise and `step` again
            Promise.resolve(next.value).then(function(v) {
                step(function() { return gen.next(v); });
            }, function(e) {
                step(function() { return gen.throw(e); });
            });
        }
        step(function() { return gen.next(undefined); });
    });
}