複数Promiseを取り扱うメソッドをみてみる

2021-08-02

概要

複数のpromiseオブジェクトを扱う際に必要なメソッドがいくつか存在します。
それぞれが解決方法が異なり、どれを使うべきか悩む時がでてきます。

ここでは、一通り出ているPromiseメソッドについて記述していきます。

Promise.all()

単一の Promise を返し、これは引数 iterable の中のすべての Promise が解決されるか、引数 iterable の中に Promise がない場合に解決されます。最初に拒否された Promise の拒否理由をもって拒否されます。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

例えば全て解決された場合を考えます。
以下のコードでは、きっと3秒後に全てのプロミスが解決され結果が返却されます。

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise1')
    }, 1000)
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise2')
    }, 2000)
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise3')
    }, 3000)
})

Promise.all([promise1, promise2, promise3])
    .then(res => {
        console.log(res)
      // ["resolve: promise1", "resolve: promise2", "resolve: promise3"]
    })

では拒否された場合はどうでしょうか。
以下ではpromise2のプロミスが拒否されたことで、結果が返却されていることがわかります。

// 省略
const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('reject: promise2')
    }, 2000)
})
// 省略

Promise.all([promise1, promise2, promise3])
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
      // reject: promise2
    })

Promise.allSettled()

与えられたすべてのプロミスが満足したか拒否された後に、それぞれのプロミスの結果を記述した配列オブジェクトで解決されるプロミスを返します。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

先程のPromise.all()と違う点は、途中で拒否されようが処理は中断しないと言う点です。

以下の例では、解決と拒否、両方とも結果として返却されていることがわかります。
きっと3秒後に解決・拒否された内容が出力されるでしょう。

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise1')
    }, 300)
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('reject: promise2')
    }, 100)
})

Promise.allSettled([promise1, promise2])
    .then(res => {
        console.log(res)
      // [{
      //     "status": "fulfilled",
      //       "value": "resolve: promise1"
      //   }, {
      //     "status": "rejected",
      //     "reason": "reject: promise2"
      //   }]
})

Promise.race()

反復可能オブジェクトの中の Promise のうちの1つが解決または拒否するとすぐに、その Promise の値または理由で解決または拒否する Promise を返します。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/race

この例では、promise2の方が早く解決するので、promise2と出力されるでしょう。

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1')
    }, 300)
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise2')
    }, 100)
})

Promise.race([promise1, promise2])
    .then(res => {
        console.log(res)
        // promise2
    })

拒否でも同様です。promise2が拒否される方が早ければ、拒否された結果が返却されるでしょう。

// 省略
const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('reject: promise2')
  }, 100)
})

Promise.race([promise1, promise2])
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log(err)
    // reject: promise2
  })

Promise.any()

このメソッドはES2021にて策定されたものです。

Promise オブジェクトの反復可能オブジェクトを受け取り、反復可能オブジェクトの中にあるプロミスの一つが満足するとすぐに、そのプロミスの値で解決される単一のプロミスを返します。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/any

先に拒否されたプロミスがあったとしても、最初に満足したプロミスで解決されます。
以下の通り、最初に拒否されますが無視をします。
次にくるのが解決されたものなので、その地点で解決されたとみなし結果を返却します。

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise1')
    }, 200)
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('reject: promise2')
    }, 100)
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('resolve: promise3')
    }, 500)
})

Promise.any([promise1, promise2])
    .then(res => {
        console.log(res)
        // resolve: promise1
    })

Promiseを扱うメリット

Web開発にて必ず必要になってくるのが非同期処理です。
async関数await演算子によって簡単に、かつ直感的に非同期を使用することができるようになっています。

しかし、一つのPromiseオブジェクトを使用することはなく、複数の値をまとめて扱うことが多々あります。

今回紹介したPromiseメソッドはきっと開発で役に立ちますので、ぜひ使用してみてください。

運営について

Natural Tearoomはシステム開発会社フロントエンドエンジニアがんちゃんが運営するメディアです。
フロントエンド技術を中心に発信しています。

· プライバシーポリシー

SNS

© 2021 天然珈琲店