「async/await」を使って、短く書く例です。
const timer = (time, text) => new Promise(resolve => { setTimeout(() => { console.log(text); resolve(); }, time); }); const func = async function() { await timer(500, '処理1'); await timer(600, '処理2'); await timer(700, '処理3'); await timer(800, '処理4'); console.log('終了'); }; func();
処理1 処理2 処理3 処理4 終了
「async/await」を使って、短く書く例その2です。「resolve」を使って値を戻します。
const timerB = time => new Promise(resolve => { setTimeout(() => { resolve(`end: ${time}`); }, time); }); const func = async function() { const res1 = await timerB(500); const res2 = await timerB(600); console.log(res1, res2); }; func();
end: 500 end: 600
「HTMLを表示 1」で書いたコードを、「async/await」を利用して短く書いてみます。
(async function() { const response = await fetch(location.href); if (! response.ok) { return } const text = await response.text(); console.log(text.replace(/>/g, '>\n')); })();
すっきりと書くことができました。このように短く読みやすくなるので、新しいプログラムを書く時は、「async/await」を使うとよいでしょう。
このコラムは、ある程度「Promise」に慣れてから読むとよいです。また、配列の反復メソッドが使える中級者以上を対象にしています。
「async/await」の処理を配列に対しておこなう時は注意が必要です。仕様を理解していないと、期待したとおりには動きません。
まず以下のような、「Promise」オブジェクトを返す共通コードと、値の配列を用意します。
const timerC = time => new Promise(resolve => { setTimeout(() => { console.log(`exec: ${time}`); resolve(`resolve: ${time}`); }, time); }); const arr = [700, 600, 500];
続いて、次の2つのコードを見てください。
配列の各要素に対して、「Promise」を利用した処理を、「await」で待機しながら実行します。そして結果を配列で受け取り、最後に「end all」を出力します。
1つ目は、よくある間違いのコードです。
(async function() { const res = arr.map(async x => await timerC(x)); console.log('end all', res); })();
end all [Promise, Promise, Promise] exec: 500 exec: 600 exec: 700
処理末の「end all」が先に出力されています。
「async」を付けた関数では、対応する関数スコープ内で「await」を待ちながら実行します。このコードの「await」と対応しているのは、内側の「async」(「map」の引数の関数)です。
またこのコードでは、結果の配列に「Promise」オブジェクトが格納されています。この部分も期待とは違います。
2つ目は、期待した動作をするコードです。
(async function() { const res = []; for (let i = 0; i < arr.length; i ++) { res.push(await timerC(arr[i])); } console.log('end all', res); })();
exec: 700 exec: 600 exec: 500 end all ['resolve: 700', 'resolve: 600', 'resolve: 500']
全ての処理が終わったあと「end all」が出力されています。結果の配列にも、期待した値が入っています。「async」と「await」の対応を確認してください。
さて、後者は期待通り動作しましたが、各「Promise」が終わってから実行するため処理時間が掛かります。通信などでは同時に読み込み、並列的に処理をおこないたいです。
この処理を並列的に処理する方法を、後の方で出てくるコラム「配列の処理 2」で紹介します。