Javascriptを使って動的なHPを作りたいと思い、まずはSleep関数のサンプルを実装し、文字列を表示させてみました。
sleep関数
次のプログラムを実装しました。
//引数に指定したミリ秒後にreturnが返ってくる
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Promiseは、設定した時間後にコールバックしてくれるという仕組みです。
ループでウェイトを作る必要がないので、他の処理への負担も少ないとのことでした。
文字列を一文字ずつ表示する関数
文字列を一文字ずつ表示するプログラムに使ってみます。
<body>
<div id="output"></div>
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function displayStringWithDelay(inputString) {
const targetElement = document.getElementById("output");
for (let i = 0; i < inputString.length; i++) {
targetElement.innerText += inputString[i];
await sleep(100);
}
}
</script>
</body>
着目する点は、async です。
これは、非同期処理を行う関数の最初に宣言するもので、関数の終了を待つことなく、次の関数が実行されます。
C言語のthreadとよく似た仕組みのようですが、threadはCPUの別のコアで実行されるのに対して、asyncは、単一スレッド内で非同期を行なっているようです。
async の有無による処理の違い
次のプログラムを実行して実験しました
<body>
<div id="output"></div>
<script>
//非同期型
async function ex1(){
await sleep(5000);
targetElement.innerText += "ex1が実行されました";
}
//同期型
function ex2(){
sleep(5000);
targetElement.innerText += "ex2が実行されました";
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
</script>
<button onclick="ex2();ex1();">test</button>
</body>
どちらもsleep関数を呼び出しているのに、ex2関数は呼出た瞬間に実行されていることがわかります。
ex2内では、sleep関数内のPromiseのコールバックが待ちきれないようです。
なお、ex1関数のasyncを外して次のようにするとエラーが起きます。
//エラーになる呼び出し方法
function ex1(){
await sleep(5000);
targetElement.innerText += "ex1が実行されました";
}
//返ってくるエラー
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules (at javascript_move.html:23:2)
反対に、次の形にするとエラーにはなりませんが、Sleepの終了を待たずに即時に実行されます。
//エラーにはならないが、sleepを待たない
async function ex1(){
sleep(5000);
targetElement.innerText += "ex1が実行されました";
}
async とawaitはセットで使う必要があるということですね。
Javascriptを使っていろいろと作れそうです。