56
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PromiseとAsync/Awaitについて

Last updated at Posted at 2021-08-03

PromiseとAsync/Awaitについて

Promiseとasync/awaitについて自分の中では理解しているけど、上手く説明できなかったので整理します。
一言で説明できるようになることを目的とします。

JavaScriptは処理を待てません!

console.log("1");

// 1秒後に実行する処理
setTimeout(() => {
  console.log("2(1秒後に実行)");
}, 1000);

console.log("3");
1
3
2(1秒後に実行)

Callback

JavaScriptは処理を待てないので、、、

function loadScript(src) {
  スクリプトを読み込む処理
}

loadScript("/myScript.js");
newFunction();  この関数はmyScript.jsを読み込みが終わるのを待ちません

このnewFunction()がmyScript.jsの内容を使用する場合にはnewFunction()は思うように動作しません。
そんな時にcallback関数という使い方があります

function loadScript (src, callback) {
  スクリプトを読み込む処理
  callback();
}

loadScript("/myScript.js", newFunction);

こうすることでスクリプトを読み込んだ後に、そのスクリプトの処理を使用する関数を呼ぶことができます。
しかし、ある非同期処理が終わった後にある非同期処理をやる、その処理が終わった後にまた次の非同期処理をやりたい、そしてまた次の、、、、、
といった場合にはネスト地獄が待っています。

loadScript("script1.js", function() {
  loadScript("script2.js", function() {
    loadScript("script3.js", function() {
      .....
    })
  })
})

script1を読み込んだ 後に script2を読み込む その後に script3を読み込む、、、
このように微妙です。これを解決するためにPromiseがありmす。

Promise

Promiseとは

Promise:約束する
~ 処理を約束する

Promiseには3つの状態がある
・pending:未解決(処理が終わるのを待っている状態)
・resolved:解決済み(処理が終わり、無事成功した状態)
・rejected:拒否(処理が失敗に終ってしまった状態)

new Promise() で作られた Promiseオブジェクトは、pendeingというPromiseStatusで作られます。
処理が成功した時にPromiseStatusがresolvedになって、thenに書かれた処理が実行される。
処理が失敗した時にPromiseStatusがrejectedになって、catchに書かれた処理が実行される。

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

promise.then(
  result => alert(result),  1秒後に "done!" を表示
  error => alert(error)  実行されない
);

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

promise.then(
  result => alert(result),  実行されない
  error => alert(error)  1秒後に "Error: Whoops!" を表示
);

Promiseクラスの四つの静的なメソッド

  1. Promise.resolve(value) – 与えられた値で promise を解決(resolve)します

指定された値でresolveされたpromiseを返す。promiseでラップ

let promise = Promise.resolve(value);
  1. Promise.reject(error) – 与えられたエラーで promise を拒否(reject)します
    error で拒否(reject)された promise を生成する。
let promise = Promise.reject(error);
  1. Promise.all(promises) – すべての promise が解決するのを待って、結果の配列を返します。 与えられた promise が拒否されると、それは Promise.all のエラーになり、他のすべての結果は無視されます。
    並列に複数の promise を実行し、すべてが準備できるまで待つためのメソッド。

以下は3秒後に解決され、[1,2,3]を返す

Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
  new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert);
  1. Promise.race(promises) – 最初の promise の解決を待ち、その結果/エラーが結果になります。

1番処理が早く完了する1が返ってくる

Promise.race([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert);

Async/Await

async/await は よりpromiseを快適に利用する特別な構文

Async関数

async を関数の前につけるだけで 関数は常にpromiseを返す。
自動的にpromiseでラップしてくれる

async function f() {
  return 1;
}

// Promise<1>
f().then(alert); // 1

Await関数

awaitはasync関数内のみで動作し、promiseが確定するまでJavaScriptを待機させる。

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

  let result = await promise; // promise が解決するまで待つ

  alert(result); // "done!"
}

f();

参考になった問題

非async から asyncを呼び出す時

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // ...ここに何を書きますか?
  // async wait() をして 10 を取得するのを待ちます
  // 覚えておいてください、"await" は使えません
}

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // 1秒後に 10を表示
  wait().then(result => alert(result));
}

f();

ここで注意なのは、f()の後に処理がある場合はそれが先に実行されてしまうことがあること
上記の関数f()のあとに以下のような処理がある時

f();
alert("ほげ");  先に実行される

参考

56
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?