JavaScriptによる非同期処理
こんにちはあっくんです。僕の肌荒れが最高潮に達してきました。もともとのアレルギー体質と日々の不眠とかから来てるかも知れません。健康って本当に大切ですね。明日、また病院に行ってみます。
それでは,JavaScriptによる非同期処理をやっていきましょー!!
JavaScriptによる非同期処理
非同期処理を書くための仕組みの一つであるPromiseがあります。asynccとawitという非同期処理を短く方法もあります。
非同期処理とは
非同期処理とは時間のかかる処理は終了をまたずに先に進め、処理が終わったタイミングで関数を実行するという方式です。
JavaScriptは基本的にシングルスレッドのプログラミング言語です。処理は1つずつ終わるのを街、次の処理へと進んで行きます。このシングルスレッドの方式は、通信などの待機時間がある処理で問題になます。待ち時間が終わるまでにすべての処理が止まり、操作不能になるからです。
 
例、処理1,2,5,6と進んだあとに3,4を実行します。setTimeout()は一定時間待機したあとに引数の関数を実行する命令です。
 
<html>
<script>
    // メインの処理の流れ。
    console.log("処理1");
    console.log("処理2");
    // 100ミリ秒後に実行する処理
    setTimeout(() => {
        console.log("処理2");
        console.log("処理3");
    }, 100);
    // メインのしょりの流れ
    console.log("処理5");
    console.log("処理6");
</script>
</html>Code language: HTML, XML (xml)非同期処理はコールバック関数を使います。非同期の処理が複数にになることもあります。その場合、コールバック関数のネストは深くなり、プログラムはみにくくなります。
 こうした問題を解決するために、Promiseという仕組みがあります。
例、非同期処理が入れ子になったプログラム。
 
<html>
<script>
    console.log("処理1");
    // 100ミリ秒待って実行
    setTimeout(() => {
        console.log("処理A");
        // 100ミリ秒待って実行
        setTimeout(() => {
            console.log("処理B");
            // 100ミリ秒待って実行
            setTimeout(() => {
                console.log("処理C");
                // 100ミリ秒待って実行
                setTimeout(() => {
                    console.log("処理D");
                    // 100ミリ秒待って実行
                    setTimeout(() => {
                        console.log("処理E");
                    }, 100);
                }, 100);
            }, 100);
        }, 100);
    }, 100);
    console.log("処理2");
</script>
</html>Code language: HTML, XML (xml)Promise
Promiseとは、約束です。Promiseオブジェクトは、後で処理することを約束して、先にすすむためのものです。
Promiseオブジェクトは、new Promise(関数)と、コールバック関数を引数にしてインスタンスを作ります。コールバック関数は、resolve(解決)とreject(拒否)という2つの関数を引数に取ります。そして、時間がかかる処理をしたあと、正常に終了すればresolve()関数を、異常に終了すればreject()関数を実行します。
構文
new Promise((resolve, reject) => {
	時間のかかる処理
	正常に終了したとき終了したときしたとき()を実行実行
	異常に終了したとき終了したときしたとき()を実行実行
})
Code language: JavaScript (javascript)Promiseオブジェクトには処理が終わったあとに、続きの処理をするためのメソッドがあります。最も一般的なメソッドはthen(関数)です。then()のコールバック関数は、resolve()やreject()を実行すると呼び出されます。resolve(),reject()に引数を設定したときは、コールバック関数の値を受け取れます。
構文
new Promise((resolve, reject) => {
	時間のかかる処理
	正常に終了したとき終了したときしたとき(dateA)を実行実行
	異常に終了したとき終了したときしたとき(dataB)を実行実行
})
.then(dataA => {
	resolve()を実行した時の処理した時の処理時の処理
	resolve()の引数を
}, dataB => {
	reject()を実行した時の処理した時の処理時の処理(書かなくてもよい
	reject()の引数を
});
Code language: JavaScript (javascript).then()は、再びPromiseオブジェクトを返します。そのため、.then()のあとに、さらに.thenを書くことができます。
構文
new Promise((resolve, reject) => {
})
.then(dataA => {
})
.then(dataA => {
})
.then(dataA => {
});
Code language: JavaScript (javascript).then()のコールバック関数の戻り値としてPromiseオブジェクトを書いたときは、その処理の終了を待って、次の.then()を実行します。戻り値がPromiseオブジェクトでないときは待機せず、すぐに次の制御が移ります。
構文
new Promise((resolveA, reject) => {
	時間のかかる処理
	正常に終了したときは()を実行実行
})
.then(data => {
	resolveA()を実行したときの処理
	変数P数P= new Promise((resolveB, reject) => {
		時間のかかる処理
		正常に終了したときは()を実行実行
	})
	return 変数P数P;
})
.then(data => {
	resolveB()を実行したときの処理
	変数P数P= new Promise((resolveC, reject) => {
		時間のかかる処理
		正常に終了したときは()を実行実行
	})
	return 変数P数P;
})
Code language: JavaScript (javascript)例、Promise。
 
<html>
<script>
    console.log("処理1");
    new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                console.log("処理A");
                resolve();
            }, 100);
        })
        .then((d) => {
            return new Promise((resolve, reject) => {
                // 100ミリ秒待って実行
                setTimeout(() => {
                    console.log("処理B");
                    resolve();
                }, 100);
            });
        })
        .then((d) => {
            return new Promise((resolve, reject) => {
                // 100ミリ秒待って実行
                setTimeout(() => {
                    console.log("処理C");
                    resolve();
                }, 100);
            });
        })
        .then((d) => {
            return new Promise((resolve, reject) => {
                // 100ミリ秒待って実行
                setTimeout(() => {
                    console.log("処理D");
                    resolve();
                }, 100);
            });
        })
        .then((d) => {
            return new Promise((resolve, reject) => {
                // 100ミリ秒待って実行
                setTimeout(() => {
                    console.log("処理E");
                    resolve();
                }, 100);
            });
        });
    console.log("処理2");
</script>
</html>Code language: HTML, XML (xml)例、Promise。非同期処理を関数を使って見やすくします。
 
<html>
<script>
    // 待機用の関数
    function wait(msg) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                console.log(msg);
                resolve();
            }, 100);
        });
    }
    console.log("処理1");
    wait("処理A")
        .then((d) => {
            return wait("処理B");
        })
        .then((d) => {
            return wait("処理C");
        })
        .then((d) => {
            return wait("処理D");
        })
        .then((d) => {
            return wait("処理E");
        });
    console.log("処理2");
</script>
</html>Code language: HTML, XML (xml)Promiseのインスタンスメソッド
Promiseオブジェクトのインスタンスメソッドは.3種類あります。
Promiseオブジェクトのインスタンスメソッド
.then(f1, f2)
resolve()のときは関数f1, reject()のときは関数f2を実行。
.catch(f1)
reject()のときは関数f1を実行。
.finally(f1)
resolve()でもreject()でも関数f1を実行。
.then()は(第1引数のみを使い)正常時の処理、 .catch()は異常時の処理、 .finally()は両方で行う最終処理で使い分けます。
例、Promise。reject()が実行されたら、間にあるresolve()は一挙に飛ばされます。
 
<html>
<script>
    // 待機用の関数
    function wait(msg, isOk = true) {
        // Promiseオブジェクトを戻り値にする。
        return new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                console.log(msg);
                if (isOk) {
                    // isOk我trueなら解決
                    resolve();
                } else {
                    // isOkがfalseなら拒否
                    reject();
                }
            }, 100);
        });
    }
    wait("処理A", false) //ここでrejectに
        .then(
            (d) => {
                return wait("処理B 成功");
            },
            (d) => {
                return wait("処理B 失敗");
            }
        )
        .then((d) => {
            return wait("処理C 成功", false);
        })
        .then((d) => {
            return wait("処理D 成功");
        })
        .then((d) => {
            return wait("処理E 成功");
        })
        .catch((d) => {
            return wait("処理F 失敗");
        })
        .finally((d) => {
            return wait("処理G 終了");
        });
</script>
</html>Code language: HTML, XML (xml)例、Promise。throw文をつかって、処理C, 処理Dを飛ばします。
 
<html>
<script>
    // 待機用の関数
    function wait(msg) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                console.log(msg);
                resolve();
            }, 100);
        });
    }
    wait("処理A")
        .then((d) => {
            throw new Error("Oh!"); //例外を起こす
            return wait("処理B");
        })
        .then((d) => {
            return wait("処理C");
        })
        .then((d) => {
            return wait("処理D");
        })
        .catch((d) => {
            return wait("処理E");
        })
        .finally((d) => {
            return wait("処理F");
        });
</script>
</html>Code language: HTML, XML (xml)Promiseの静的メソッド
Promiseの静的メソッドは複数のPromiseをまとめて扱えます。 並列の処理です。
Promiseオブジェクトの静的メソッド
.all(a)
Promiseの配列aが全て解決すれば、解決とみなして結果の配列をあとの処理に送る。
1つでも拒否されれば拒否と見なし、結果をあとの処理に送ります。
.any(a)
Promiseの配列aが1つでも解決すれば、解決と見なして結果をあとの処理に送る。全て拒否すれば拒否と見なし、結果をあとの処理に贈ります。
.allSettled(a)
Promiseの配列aの処理が全て終われば、解決とみなしてすべての結果を配列にして送ります。
.race(a)
Promiseの配列aの処理が1つでも終われば次の処理に移行します。その1つの処理が解決なら解決と見なし、拒否なら拒否とみなします。
例、Promise.all()。 全てが解決するか、拒否が起きれば、先に進みます。
 
<html>
<body>
    <script>
        // 待機用の関数
        function p(tm, isResolve = true) {
            // Promiseオブジェクトを戻り値にする
            return new Promise((resolve, reject) => {
                // tmミリ秒待って実行
                setTimeout(() => {
                    // コンソールに情報を出力
                    console.log(tm, isResolve ? "resolve" : "reject");
                    if (isResolve) {
                        // isResolveがtrueなら解決
                        resolve(`${tm}:ok`);
                    } else {
                        // isResolveがfalseなら拒否
                        reject(`${tm}:err`);
                    }
                }, tm);
            });
        }
        // Promise.all()その1
        setTimeout(() => {
            console.log("--- Promise.all() その1 ---");
            // Promiseオブジェクトの配列を作成
            const arr = [p(1, true), p(2, true), p(3, true)];
            // Promise.all()の処理
            Promise.all(arr)
                .then((data) => {
                    // 成功時
                    console.log("--> then :", data);
                })
                .catch((data) => {
                    // 失敗
                    console.log("--> catch :", data);
                });
        }, 0);
        // Promise.all()その2
        setTimeout(() => {
            console.log("--- Promise.all() その2 ---");
            // Promiseオブジェクトの配列を作成
            const arr = [p(1, true), p(2, false), p(3, true)];
            // Promise.all()の処理
            Promise.all(arr)
                .then((data) => {
                    // 成功時
                    console.log("--> then :", data);
                })
                .catch((data) => {
                    // 失敗時
                    console.log("--> catch :", data);
                });
        }, 100);
    </script>
</body>
</html>Code language: HTML, XML (xml)例、Promise.any()。 全てが拒否されるか、解決が起きれば先に進ます。
 
<html>
<script>
    // 待機用の関数
    function p(tm, isResolve = true) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // tmミリ秒待って実行
            setTimeout(() => {
                // コンソールに情報を出力
                console.log(tm, isResolve ? "resolve" : "reject");
                if (isResolve) {
                    // isResolveがtrueなら解決
                    resolve(`${tm}:ok`);
                } else {
                    // isResolveがfalseなら拒否
                    reject(`${tm}:err`);
                }
            }, tm);
        });
    }
    // Promise.any()その1
    setTimeout(() => {
        console.log("--- Promise.any() その1 ---");
        // Promiseオブジェクトの配列を作成
        const arr = [p(1, false), p(2, true), p(3, false)];
        Promise.any(arr)
            .then((data) => {
                // 成功時
                console.log("--> then :", data);
            })
            .catch((data) => {
                // 失敗時
                console.log("--> catch :", data);
            });
    }, 0);
    // Promise.any()その2
    setTimeout(() => {
        console.log("--- Promise.any() その2 ---");
        // Promise.any()の処理
        const arr = [p(1, false), p(2, false), p(3, false)];
        // Promise.any()の処理
        Promise.any(arr)
            .then((data) => {
                // 成功時
                console.log("--> then :", data);
            })
            .catch((data) => {
                // 失敗時
                console.log("--> catch:", data);
            });
    }, 100);
</script>
</html>Code language: HTML, XML (xml)例、Promise.allSettled()。 全ての処理が終われば、先に進みます。全ての結果を配列で受け取ります。
 
<html>
<script>
    // 待機用の関数
    function p(tm, isResolve = true) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // tmミリ秒待って実行
            setTimeout(() => {
                // コンソールに出力
                console.log(tm, isResolve ? "resolve" : "reject");
                if (isResolve) {
                    // isResolveがtrueなら解決
                    resolve(`${tm}:ok`);
                } else {
                    // isResolveがfalseなら拒否
                    reject(`${tm}:err`);
                }
            }, tm);
        });
    }
    // Promiseオブジェクトの配列を作成
    const arr = [p(1, false), p(2, true), p(3, false)];
    // Promise.allSettled()の処理
    Promise.allSettled(arr).then((data) => {
        console.log("--> then :", data);
    });
</script>
</html>Code language: HTML, XML (xml)例、 Promise.race()。 最初の1つの処理が終われば、先に進みます。解決でも拒否でも構いません。
 
<html>
<script>
    // 待機用の関数
    function p(tm, isResolve = true) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // tmミリ秒待って実行
            setTimeout(() => {
                // コンソールに出力
                console.log(tm, isResolve ? "resolve" : "reject");
                if (isResolve) {
                    // isResolveがtrueなら解決
                    resolve(`${tm}:ok`);
                } else {
                    // isResolveがfalseなら拒否
                    reject(`${tm}:err`);
                }
            }, tm);
        });
    }
    // Promise.race()その1
    setTimeout(() => {
        console.log("--- Promise.race() その1 ---");
        // Promiseオブジェクトの配列を作成
        const arr = [p(1, true), p(2, false), p(3, true)];
        Promise.race(arr)
            .then((data) => {
                // 成功時
                console.log("--> then : ", data);
            })
            .catch((data) => {
                // 失敗時
                console.log("--> catch :", data);
            });
    }, 0);
    // Promise.race()その2
    setTimeout(() => {
        console.log("--- Promise.race() その2 ---");
        // Promiseオブジェクトの配列を作成
        const arr = [p(1, false), p(2, true), p(3, false)];
        // Promise.race()の処理
        Promise.race(arr)
            .then((data) => {
                // 成功時
                console.log("--> then :", data);
            })
            .catch((data) => {
                // 失敗時
                console.log("--> catch :", data);
            });
    }, 100);
</script>
</html>Code language: HTML, XML (xml)asyncとawait
asyncは非同期という意味です。                                                  awaitは待つという意味です。
asyncとawaitを使った書き方でシンプルに非同期処理ができます。
async functionと書くことで、その関数は非同期処理を扱う関数になります。async function内では、非同期の関数の前にawaitをつけることで、Promiseの処理を待ってからプログラムを進めます。awaitをつけた関数の戻り値は、resolve()の引数になります。
構文
async function 関数名数名引数) {
	処理
	await 非同期の関数期の関数()
	変数= await 非同期の関数期の関数()
		//非同期の関数内で、resolve(v)を実行したなら、vが変数に入る。
	処理
}Code language: JavaScript (javascript)例、async await。
 
<html>
<script>
    // 待機用の関数
    function wait(msg, isResolve = true) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                if (isResolve) {
                    if (isResolve) {
                        // isResolveがtrueなら解決
                        resolve(msg);
                    } else {
                        // isResolveがfalseなら拒否
                        reject(`error (${msg}`);
                    }
                }
            }, 100);
        });
    }
    // async実験用の関数
    async function exec() {
        console.log("--- 処理開始 ---");
        console.log(await wait("処理A"));
        console.log(await wait("処理B"));
        console.log("処理途中");
        const c = await wait("処理C");
        const d = await wait("処理D");
        console.log(c);
        console.log(d);
        console.log("--- 処理終了 ---");
    }
    // 処理の開始
    console.log("--> 処理1");
    console.log("--> exec()", exec());
    console.log("--> 処理2");
</script>
</html>Code language: HTML, XML (xml)例、awaitの処理をtry catch文で加工と、reject()をcatchで捕まえられます。
 
<html>
<script>
    // 待機用の関数
    function wait(msg, isResolve = true) {
        // Promiseオブジェクトを戻り値にする
        return new Promise((resolve, reject) => {
            // 100ミリ秒待って実行
            setTimeout(() => {
                if (isResolve) {
                    // isResolveがtrueなら解決
                    resolve(msg);
                } else {
                    // isResolveがfalseなら拒否
                    reject(`error (${msg})`);
                }
            }, 100);
        });
    }
    // async実験用の関数
    async function exec() {
        console.log("--- 処理開始 ---");
        console.log(await wait("処理A"));
        console.log(await wait("処理B"));
        // try catch文
        try {
            // 例外が発生するかも知れない処理
            console.log(await wait("処理C", false));
            console.log(await wait("処理D"));
        } catch (e) {
            // 例外発生時の処理
            console.log("例外発生", e);
        }
        console.log("--- 処理終了 ---");
    }
    // 処理の開始
    exec();
</script>
</html>Code language: HTML, XML (xml)読んでいただいて、ありがとうございました!JavaScript完全入門は2021年、2月発売です。
 
				