Promiseとasyncとawait

Promiseとasync、awaitの使い方を理解するために書いたサンプルコード。 setTimeoutを使って1秒後に画面に文字列を出力する。

Promiseとthen()

Promiseオブジェクトの生成とthen()メソッドの利用例。

<html>
<head>
  <meta charset="utf-8"/>
  <title>Promiseとthen()</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

function main() {
  const promise = slowFunction();
  // Promiseの処理が完了したら(resolveが呼ばれたら)、結果を出力
  promise.then(result => {
    // resolve関数の引数で渡された値がresultに格納される
    print(result);
  })
}

function slowFunction() {
  // Promiseオブジェクトを返す
  return new Promise(resolve => {
    // 1秒後にresolveを呼び出す
    setTimeout(() => {
      resolve("Result");
    }, 1000);
  });
}
</script>
</body>
</html>

Promiseとthen() - JSFiddle

Promiseとreject()

Promiseオブジェクトの例外処理、reject()とcatch() メソッドを使う。

reject()を呼ぶと、catch()メソッドに渡したコールバック関数が実行される。

<html>
<head>
  <meta charset="utf-8"/>
  <title>Promiseとreject、catch()</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

function main() {
  const promise = slowFunction();
  // Promiseの処理が完了したら(resolveが呼ばれたら)、結果を出力
  promise.then(result => {
    print("Success");
  }).catch((message) => {
    // reject関数で渡された引数がcatchの引数に渡されてくる
    print(message);
  })
}

function slowFunction() {
  return new Promise((resolve, reject) => {
    // 1秒後にrejectを呼ぶ
    setTimeout(() => {
      // エラー内容などはreject関数の引数で渡す
      reject("Error!");
    }, 1000);
  });
}
</script>
</body>
</html>

Promiseとreject、catch() - JSFiddle

Promiseとthrow

then()メソッドに渡したコールバック関数内で例外を発生させる場合はthrowを使う。 catchメソッドに渡したコールバック関数が呼ばれる。

<html>
<head>
  <meta charset="utf-8"/>
  <title>Promiseとthrow、catch()</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

function main() {
  const promise = slowFunction();
  // When it is finished promise(called resolved), then output the result.
  promise.then(result => {
    throw new Error("Error!");
  }).catch((error) => {
    // result is Error object.
    print(error);
  })
}

function slowFunction() {
  // Returns promise object.
  return new Promise((resolve, reject) => {
    // Execute resolve function after a second.
    setTimeout(() => {
      resolve("Result");
    }, 1000);
  });
}
</script>
</body>
</html>

Promiseとthrow、catch() - JSFiddle

Promiseをawait構文で待つ

Promiseオブジェクトの処理が終わるのをawait構文で待つ例。

<html>
<head>
  <meta charset="utf-8"/>
  <title>Promiseとawait構文</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

// "await"構文は"async"キーワード付きの関数内でしか使えない
async function main() {
  // awaitで呼び出すと、resolveかrejectが呼ばれるまで止まる
  // resolveで渡された引数は、戻り値として返却される
  result = await slowFunction();
  print(result);
}

function slowFunction() {
  // Promiseオブジェクトを返す
  return new Promise(resolve => {
    // 1秒後にresolve関数を呼ぶ
    setTimeout(() => {
      resolve("Result");
    }, 1000);
  });
}
</script>
</body>
</html>

Promiseとawait構文 - JSFiddle

asyncとawait

async functionで関数を実装すれば、Promiseの発行を減らせるのと、then()のメソッドチェーン地獄がマシになる

<html>
<head>
  <meta charset="utf-8"/>
  <title>asyncとawait</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

// "await"構文は"async"キーワード付きの関数内でしか使えない
async function main() {
  // async functionの結果が返ってくるまで待つ
  result = await slowFunction();
  print(result);
}

async function slowFunction() {
  // setTimeoutをPromiseでラップし、終わるまでawaitで待つ
  await new Promise(resolve => setTimeout(resolve, 1000));
  // async functionの結果として文字列を返却
  return "Result";
}
</script>
</body>
</html>

asyncとawait - JSFiddle

async、awaitと例外処理

async、awaitを使う場合、例外はthrowで発生させて、try catch構文で処理できる。

<html>
<head>
  <meta charset="utf-8"/>
  <title>asyncとawait、throw()</title>
</head>
<body>
<button onclick="main()">Run</button>
<div id="output">
</div>
<script>
function print(text) {
  const element = document.getElementById('output');
  element.innerText = element.innerText + text + '\n';
}

// "await"構文は"async"キーワード付きの関数内でしか使えない
async function main() {
  // async functionでthrowされた例外はtry catch構文で処理できる
  try {
    result = await slowFunction();
    print(result);
  } catch (error) {
    print(error);
  }
}

async function slowFunction() {
  // setTimeoutをPromiseでラップし、終わるまでawaitで待つ
  await new Promise(resolve => setTimeout(resolve, 1000));
  // throwで例外を発生させる
  throw new Error("Error in async function!");
  return "Result";
}
</script>
</body>
</html>

asyncとawait、throw() - JSFiddle

参考