AWS lambda で Node.js と向きう合う必要が出てきたので、最近のモダンな JS を理解する
最近は async/await が使えるらしいが、内部的には Promise を使っているらしいので、まずは Promise から理解する
Promise とは?
非同期処理の実行結果(成功 or 失敗) の受け取り口を用意して、非同期の管理を容易にするためのオブジェクト
コールバック地獄のしんどさを回避するために生まれた
つかいかた
new Promise
する
- 第一引数は、引数が2つある関数
- 関数の第1引数には、正常終了時に呼び出す関数
- 関数の第2引数には、異常終了時に呼び出す関数
new Promise
の戻り値は、then()
とcatch()
を持つオブジェクト-
then()
には正常終了時に呼ばれる関数を渡す -
catch()
には異常終了時に呼ばれる関数を渡す- 例外を勝手に拾ってくれたりはしないので、自前で例外をコントロールする必要がある
-
then()
かcatch()
が呼ばれた時点で、promise に渡した関数が実行される
正常終了例
const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('foo'); }, 10); }); promise.then((value) => { console.log("then"); console.log(value); }).catch((value) => { console.log("catch"); console.log(value); });
出力結果
then foo
異常終了例
const promise = new Promise((resolve, reject) => { setTimeout(() => { reject('foo'); }, 10); }); promise.then((value) => { console.log("then"); console.log(value); }).catch((value) => { console.log("catch"); console.log(value); });
出力結果
catch foo
Promise のチェーン
then()
の戻り値を Promise
オブジェクトにすることで、Promise をチェーンできる
これにより、非同期処理を同期的に実行できる
例
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('promise1'); }, 10); }); promise1.then((value) => { console.log("then 1"); return new Promise((resolve, reject) => { setTimeout(() => { resolve('promise2'); }, 10); }); }).then((value) => { console.log("then 2"); });
出力結果
then 1 then 2
Promise#all
複数 Promise の並列実行ができる
正常終了例
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { console.log('promise1') resolve('promise1'); }, 10); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { console.log('promise2') resolve('promise2'); }, 10); }); Promise.all([ promise1, promise2 ]).then((value) => { console.log(value) console.log('finished') });
then()
には、各 Promise
の resolve
の引数を配列にしたものが渡される
promise1 promise2 [ 'promise1', 'promise2' ] finished
異常終了例
1つでも reject()
が呼ばれたら catch()
が呼ばれる
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { reject('promise1'); }, 10); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { reject('promise2'); }, 10); }); Promise.all([ promise1, promise2 ]).then((value) => { console.log(value) console.log('finished') }).catch((value) => { console.log(value) console.log('catch') });
出力結果
promise2 catch
reject()
が複数発生する場合も、早いもの勝ちで最初の reject()
の引数が渡される
処理自体は最後まで行われる
Promise.race()
複数 Promise のうち、1つでも処理が完了したら then()
が呼ばれる