Promiseのcatch内でのreturnとthrow

Promiseの(Promiseと言ってもES6 Promisesじゃなくてbluebirdなんだけど)catch内でのreturnとthrowの挙動の違いについて知らなくて試したのでメモ。

環境はnode.js 0.10.33とbluebird 2.3.11です。

var Promise = require('bluebird');

function a() {
  return new Promise(function(resolve, reject) {
    reject(1);
  }).catch(function(err) {
    return err;
  });
}

a().then(function(data) {
  console.log('then');
  console.log(data);
});

catchの中でreturnする。

then
1

使う方はthenで値を取れる。

var Promise = require('bluebird');

function a() {
  return new Promise(function(resolve, reject) {
    reject(1);
  }).catch(function(err) {
    //return err;
    throw err;
  });
}

a().then(function(data) {
  console.log('then');
  console.log(data);
});

catchの中でthrowする。

Possibly unhandled Error: 1
    ...

catchしてないですよ、とエラーが出力される。これはbluebirdが親切な出力してるのかな。

var Promise = require('bluebird');

function a() {
  return new Promise(function(resolve, reject) {
    reject(1);
  }).catch(function(err) {
    //return err;
    throw err;
  });
}

a().then(function(data) {
  console.log('then');
  console.log(data);
}).catch(function(err) {
  console.error('catch');
  console.error(err);
});

使う方でcatchをする。

catch
1

使う方でcatchできた。

まとめ

  • catchの中でreturnをするとthenに値を渡せる
  • catchの中でthrowをするとcatchに値を渡せる

ということか。今までresolveとrejectにそれぞれ値を渡す方法しかしらなかった。

上記がわかったので場合によってエラーが発生したらデフォルト値を渡す、というようなことが簡潔に書けるようになったと思う。

唯一気がかりなのは、bluebirdを使っているのでES6 Promisesもこういう挙動なのかどうかわからないというところかな……


いつもPromisesで困ったときはJavaScript Promiseの本を読んでるのだけど、今回調べた内容は書いてあるのかな。

読み直してみたらthrowとか使うよりnew Promiseしてrejectを使ったほうがいい、と書いてある。returnとかthrowしたほうが楽だから、と思ってこれを調べたのだけど、それよりもこちらの方が欠点が少ないようなのでちゃんとPromiseを生成して返すようにしよう。