async/await隐式返回promise?

Ale*_*lls 85 javascript node.js async-await ecmascript-next

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

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

var ret = getVal();
console.log(ret);
Run Code Online (Sandbox Code Playgroud)

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

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

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

更清楚的是,上述和之间存在差异

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
Run Code Online (Sandbox Code Playgroud)

在我的概要中,行为确实与传统的return语句不一致.看来,当您从async函数中显式返回非promise值时,它会强制将其包装在promise中.我没有一个大问题,但它确实违反了普通的JS.

Nat*_*all 102

返回值始终是一个承诺.如果您未明确返回承诺,则您返回的值将自动包含在承诺中.

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));
Run Code Online (Sandbox Code Playgroud)

同样的事情,即使有一个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));
Run Code Online (Sandbox Code Playgroud)

Promises自动解包,所以如果你确实从async函数中返回一个值的promise ,你将收到一个值的承诺(不是对值的承诺).

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));
Run Code Online (Sandbox Code Playgroud)

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

ES6的功能不会返回与...完全相同的值return.这些函数称为生成器.

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

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

// Logs 'test'.
console.log(foo().next().value);
Run Code Online (Sandbox Code Playgroud)

  • 静态方法Promise.resolve"返回的值将自动包含在一个promise中",即,如果async函数的return语句是 - return x; 它隐含地变成了 - 返回Promise.resolve(x); (3认同)

Jon*_*ell 19

我查看了规范并找到了以下信息.简短的版本是一个async function产生Promises 的发电机的desugars .所以,是的,异步函数返回promises.

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

async function <name>?<argumentlist><body>
Run Code Online (Sandbox Code Playgroud)

Desugars:

function <name>?<argumentlist>{ return spawn(function*() <body>, this); }
Run Code Online (Sandbox Code Playgroud)

其中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); });
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案主要是对规范的参考,经过审查,我不认为有任何混淆。确实,异步函数返回 Promise,但为了做到这一点,它们对产生 Promise 的生成器进行脱糖处理。 (6认同)

Joh*_*kel 5

你的问题是:如果我创建一个async函数,它是否应该返回一个承诺?回答:做任何你想做的事,Javascript 会为你修复它。

假设doSomethingAsync是一个返回承诺的函数。然后

async function getVal(){
    return await doSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)

完全一样

async function getVal(){
    return doSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)

你可能在想“ WTF,这些怎么可能一样? ”你是对的。该async神奇地包裹并承诺值,如果必要的

更奇怪的是,doSomethingAsync可以写成有时返回承诺,有时返回承诺。仍然两个功能完全相同,因为await也是magic如有必要,它会打开一个 Promise 但它不会影响非 Promise 的东西。