Proimise の活用

ES2015 で 追加された Promise の使い方を紹介します。

Promise は JavaScript 内で非同期処理を行う際に用いられるオブジェクトです。

API の発行やファイルの読み込みなど時間のかかる処理を実行する場合、JavaScriptの世界では、通常非同期処理が用いられます。
最近のJavaScript における非同期処理では、ハンドリングに Promise を用いるケースがほぼ標準的な方法になってきています。

例えば、 API 通信で用いる axios は Promise を返します。

const promise = axios.get(url)

Promise は then 関数で、処理終了後の処理を指示できます

const promise = axios.get(url)
promise.then( (result) => {
  // do something
} )

promise.then( (result) => {
  // do another something
} )

上記の用にして、Promiseの完了後のコールバックは複数指定することが出来るようになっています。

then は返り値として、新しい Promise を生成します。

const promise = axios.get(url)
const promise2 = promise.then( (result) => {
  // do something
  return anotherResult
} )
promise2.then( (anotherResult) => {
  // do another something
} )

上記のようにする事で、// do another something// do something の後で実行されます。

また // do something で生成・加工した新しい値を // do another something 側で引数として受け取る事ができるようになります。

上記のコードはメソドチェーンを用いて以下のように記述するのが一般的です。

axios.get(url).then( (result) => {
  // do something
  return anotherResult
} ).then( (anotherResult) => {
  // do another something
} )

例外系の処理

then の第一引数に渡したクロージャは、Promise が正常に終了しなかった場合にはコールされません。
エラー発生時の処理は、第二引数にクロージャを渡して指定する事ができます。

const promise = axios.get(url)
promise.then( (result) => {
  // do something
  return anotherResult
}, (err) => {
  // handle error
})

引数にクロージャが二つ入るのはコードの可読性を下げるため、 then(null, cb) の エイリアスである catch を使用して以下のように記述するのが一般的です。

const promise = axios.get(url)
promise.then( (result) => {
  // do something
  return anotherResult
}).catch( (err) => {
  // handle error
})

Promise の作成

例えば Promise を想定する処理のモックを作りたいときや、古い形式のライブラリなどがコールバックの形態を取る時、イチからPromiseを作る必要が出てくるかもしれません。

Promise の生成には new Promise を用いて以下のように記述します。

const promise = new Promise( (resolve)=>{
  setTimeout( ()=>{
    resolve()
  }, 2000 )
} )

上記は 2 秒後に処理が完了するPromiseの例です。

new Promise はクロージャを引数にとり、クロージャの引数で習得できる resolve 関数を処理が完了したタイミングで習得できるようにします。

resolve をコールする際に引数に渡した値は then のクロージャの引数で結果として取得できます。

const promise = new Promise( (resolve)=>{
  setTimeout( ()=>{
    resolve("hello world")
  }, 2000 )
} ).then( (message)=>{
  console.log(message)
} )

Promise の中で Error が投げられた場合、catchがコレを補足します。

const promise = new Promise( (resolve)=>{
  setTimeout( ()=>{
    resolve("hello world")
  }, 2000 )
  throw new Error("....")
} ).then( (message)=>{
  console.log(message) // <- 実行されない
} ).catch( (e)=>{
  console.log(e)
} )

単純に、モック目的等で、解決済みの Promise または エラーを起こしたPromiseが必要な場合、
Promise.resolve()Promise.reject() を利用するのも良いでしょう。

Promise の合成

複数の Promise を 合成する Promise.all という関数があります。

const p1 = Promise.resolve(123);
const p2 = new Promise( (resolve)=>{
  setTimeout(()=>{
    resolve(456)
  }, 1000);
});

Promise.all([p1, p2]).then( (results)=>{
  console.log(results); // [123, 456]
});

Promise.all() は配列で複数のPromiseを引数に取ります。

Promise が全て完了したタイミングで then がコールされ、クロージャの引数にはそれぞれの結果が配列で取得可能です。

参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Using_promises

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です