1. ホーム
  2. javascript

[解決済み] async/awaitは暗黙のうちにプロミスを返すのか?

2022-05-30 08:42:39

質問

でマークされた非同期関数が、この関数と同じように動作することを知りました。 async キーワードでマークされた非同期関数は、暗黙のうちにプロミスを返すと読みました。

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

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

を仮定していますが、これは首尾一貫していません...。 doSomethingAsync() はプロミスを返し、await キーワードはプロミスそのものではなく、プロミスからの値を返すと仮定すると、私の getVal 関数は は暗黙のプロミスではなく、その値を返すはずです。

では、具体的にはどうなのでしょうか?asyncキーワードでマークされた関数は暗黙のうちにプロミスを返すのでしょうか、それとも何を返すかコントロールできるのでしょうか?

もしかして、明示的に何かを返さなければ、暗黙のうちにプロミスを返しているのでは...?

より明確にするために、上記と

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

私の概要では、動作は確かに従来のreturn文と矛盾しています。約束のない値を明示的に async 関数からプロミスでない値を明示的に返すと、それを強制的にプロミスでラップしてしまうようです。 大きな問題はないのですが、通常のJSに反しています。

どうすれば解決する?

戻り値は常にプロミスになります。明示的にプロミスを返さない場合、返す値は自動的にプロミスにラップされます。

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

プロミスは自動的にアンラップされます。 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));


私の概要では、この動作は確かに従来の returnステートメントと矛盾しています。非同期関数からプロミスでない値を明示的に返すと 非同期関数からプロミスでない値を明示的に返すと、それを強制的に プロミスで強制的に包むようです。大きな問題はないのですが、通常の JSです。

ES6には、全く同じ値を返さない関数があります。 return . これらの関数はジェネレータと呼ばれます。

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

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

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