Promise と非同期関数


JavaScript では、一部の操作は非同期であり、これらの非同期操作の多くは promise を介して通知されます.

たとえば、API からのデータのフェッチは非同期操作です. API からのデータが完全にダウンロードされるまで待つ必要があります.したがって、fetch を呼び出してもデータは得られません.代わりに、その関数の最初のパラメーターとして、その値を受け取るために別の関数を呼び出す必要があるプロミスを提供します.

Promise を使用して、使用可能なインスタンスの結果を取得するには、then メソッドを呼び出し、その関数を最初のパラメーターとして渡します.

次に例を示します.

const fetchPromise = fetch('http://example.com/some-api/');


fetchPromise.then(response => {
  // Do something with `response` here.
  //
  // Note: the `response` object doesn't actually contain the data. You will
  // need to invoke either `response.text()` to extract the data into a string
  // object, or `response.json()` to extract the data into an object, if the
  // incoming data is valid JSON.
});

fetch を使用すると、 response オブジェクトにアクセスできます.

しかし、response オブジェクトから値を抽出する必要があります.そして、それは response.text() または response.json() を呼び出すことによって行われます.これらの方法は両方とも約束をもたらします!

応答のテキスト値を抽出する場合、上記のコードは次のようになります.

const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text()

  textPromise.then(value => {
    // The paramter `value` will be the extracted string.
  });
});


しかし、それは良くなります.

配列には flatMap 関数があり、戻り値として別の配列を受け入れる方法を知っていますか?

promises の then メソッドは flatMap のように動作し、then のコールバック関数から別の promise を返すことができます.

したがって、テキスト値を抽出するには、上記の関数を次のように呼び出すことができます.

const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text();

  return textPromise;
});


上記では、promise を返しただけです.しかし、どうやって価値を抽出するのでしょうか?

これに入る前に、この重要な事実にも注意してください: then メソッドは常に promise を返します!

そして、その約束は、大まかに言えば、 then のコールバックによって返されるものとまったく同じになります.

したがって、テキストを抽出するには、上記のコードは次のようになります.

const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text();

  return textPromise;
}).then(text => {
  // The value will be in `text`
});


promise が通常どこから来るかを確立したので、上記のコードを短くしましょう.

fetch('https://example.com/some-api/')
  .then(response => response.text())
  .then(text => {
    // The value will be in `text`
  });


上記の API が文字列を生成し、その文字列を使用して別の API 呼び出しを呼び出すことができるとします.それをしましょう.

それを行うには多くの方法があります.

呼び出しをネストできます.

fetch('https://example.com/some-api/')
  .then(response => {
    return response.text()
      .then(text => {
        return fetch(`https://example.com/some-api/{text}`)
          .then(response => response.text());
      });
  })
  .then(text => {
    // The value will be in `text`
  });


一部の呼び出しをネストできます.おそらく、「応答からテキストへの抽出」ロジックをグループ化するためです.

fetch('https://example.com/some-api/')
  .then(response => response.text())
  .then(text => {
    return fetch(`https://example.com/some-api/${text}`)
      .then(response => response.text());
  })
  .then(text => {
    // The value will be in `text`
  });


または、すべてを順次にします.

fetch('https://example.com/some-api')
  .then(response => response.text())
  .then(text => {
    return fetch(`https://example.com/some-api/${text}`)
  })
  .then(response => response.text())
  .then(text => {
    // The value will be in `text`
  });


非同期関数



OK、上記の then の呼び出しは、多くの状況で面倒です.したがって、then 呼び出しの数を制限する解決策は、async 関数を使用することです.
async 関数は次のようになります.

async function something() {
  return 42;
}


非同期関数は単に何かを返すだけではありません.それは約束を返すだけです!

したがって、something() を呼び出すと promise が生成されます.

something()
  .then((value) => {
    console.log(value); // should print 42
  });


それはさらに良くなります.非同期関数を使用すると、 then を呼び出さずに promise を解決できます.そのためには await キーワードを使用します.

たとえば、fetch が非同期関数内で呼び出される場合、次のようになります.

async function doSomething() {
  const response = await fetch('https://example.com/some-api');
  return response.text();
}


非同期関数は promise を返すため、上記のフェッチ呼び出しを次のように簡略化できます.

fetch('https://example.com/some-api')
  .then(async response => {
    const text = await response.text();
    const response2 =
      await fetch(`https://example.com/some-api/${text}`);
    return response2.text();
  });


あなたのことはわかりませんが、私は余分な response 変数のファンではありません.解決策は、then を使用して、これらの変数を作成しないようにすることです.

fetch('https://example.com/some-api')
  .then(async response => {
    const text = await response.text();
    return fetch(`https://example.com/some-api/${text}`)
      .then(response => response.text());
  });