53
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Promise.allのcatchのタイミング

Last updated at Posted at 2017-09-23

Promise.allのcatchのタイミングの扱いでつまった話を紹介します

Promiseとは

  • 非同期処理を記述できる
  • 並行処理、直列処理を記述できる

参考:JavaScript Promiseの本

エラーの扱い

並行処理の失敗をハンドリングしたい場合、各並行処理内で失敗した時にrejectメソッドを呼ぶようにします。

sample1.js
//並行処理1(失敗)
const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("promise1");
        reject();
    }, 2000)
});
//並行処理2
const promise2 = new Promise((resolve, reject) => {
    console.log("promise2");
    resolve();
});

Promise.all([promise1, promise2]).then(() => {
    console.log("done");
}).catch(() => {
    console.log("error");
});

上記を実行すると、errorが出力されます。

promise2
promise1
error

並行処理のうち、一つでも失敗(reject)すると、Promise.allのcatchブロック内が実行されます。

catch内実行されても他の並行処理が実行されてしまう

上のサンプルでは二つの並行処理のうち、一つで失敗するパターンですが次は両方失敗するパターンを実行してみます。

sample2.js
//並行処理1(失敗)
const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("promise1");
        reject();
    }, 2000)
});
//並行処理2(失敗)
const promise2 = new Promise((resolve, reject) => {
    console.log("promise2");
    reject();
});

Promise.all([promise1, promise2]).then(() => {
    console.log("done");
}).catch(() => {
    console.log("error");
});

すると以下のようになります。

promise2
error
promise1

並行処理1はsetTimeoutで2秒後にコールバック内の処理が実行されるので、先に並行処理2が実行されます。並行処理2はconsole.log(promise2)が呼ばれた直後にrejectメソッドを呼んでいるので、失敗となります。よって、すぐにPromise.allのcatchブロックが実行されてしまいます。しかし、並行処理1は未だ実行中なので、errorが出力された後にpromise1が出力されます。このように、並行処理のうち一つでも失敗したらcatchブロックが実行されますが、実行中の他の並行処理を待たずに実行されてしまいます。

resolveでハンドリングする

rejectを呼んでしまうと、待たずに実行されてしまうので、resolveを呼んだ上でエラーハンドリングするようにします。

sample3.js
//並行処理1(失敗)
const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("promise1");
        resolve(new Error());
    }, 2000)
});
//並行処理2(失敗)
const promise2 = new Promise((resolve, reject) => {
    console.log("promise2");
    resolve(new Error());
});

Promise.all([promise1, promise2]).then((results) => {
    console.log("done");
    const includeError = results.some((result) => result instanceof Error);
    if(includeError){
        console.log("promise error");
    }
}).catch(() => {
    console.log("error");
});

すると、並行処理の実行が完了したあとにエラー処理を実行することができます。

promise2
promise1
done
promise error
53
34
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?