19352


**コード1 ／ 期待通り**

[code]

    "use strict";
    var obj = new Promise(function (resolve, reject) {
      reject('テスト')
    })
    obj.catch(function (e) {
    })
    console.log(obj);
    
[/code]

> Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "テスト"}

* * *

**コード2 ／ 期待通りではない**

[code]

    "use strict";
    var obj = new Promise(function (resolve, reject) {
      reject('テスト')
    }).catch(function (e) {
    })
    console.log(obj);
    
[/code]

> Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

* * *

**コード3 ／ 期待通りではない**  
・コード2がうまくいかなかったのは実行順番に問題があると思い、全体を()で囲った内容を変数へ格納するよう変更

[code]

    "use strict";
    var obj = (
      new Promise(function (resolve, reject) {
        reject('テスト')
      }).catch(function (e) {
      })
    )
    console.log(obj);
    
[/code]

> Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

* * *

**質問**  
・コード3 が コード1 と同じ結果にならないのは何故でしょうか？


CC BY-SA 3.0
2015-11-26T22:51:32.723
19345
2015-11-27T12:00:15.880
7886
question
ecmascript-6
Promiseチェーンの実行される順番が良く分からないのですが


then/catchの戻り値は新しいPromiseです。

コード１は自分で作成したPromiseを出力しています。  
コード２及び３はcatchの戻り値（新しいPromise）を出力しているので、コード１と結果が異なります。

statusがpendingになってる理由はPromiseは非同期実行されるからです。

[code]

    window.setTimeout(function(){
        console.log(onj);
    }, 1000);
    
[/code]

このようにすればstatusが"resolved"になります。

"rejected"ではなく"resolved"になる理由は、  
then/catchで作成されるPromiseは、最初に作成したPromiseのresolve/rejectの状態ではなく、then/catchで指定した関数の実行で例外が発生すればreject、発生しなければresolveされるPromiseだからです。

[code]

    var obj = new Promise(function (resolve, reject) {
      reject('テスト');
    });
    
    var newPromise = obj.catch(function (e) {
        console.log('catch');
    });
    
    newPromise.then(
       function(){
          console.log('resolve');
       },
       function(){
          console.log('reject');
       }
    );
    
[/code]

例えば、このような場合'catch'、'resolve'と表示されます。  
これは、obj.catchで指定した関数が問題なく処理された為、newPromiseは'reject'ではなく'resolve'側が実行されます

[code]

    var obj = new Promise(function (resolve, reject) {
      resolve('テスト');
    });
    
    var newPromise = obj.then(
       function(){
          console.log('resolve-1');
          throw 'resolve-error'
       },
       function(){
          console.log('reject-1');
       }
    );
    newPromise.then(
       function(){
          console.log('resolve-2');
       },
       function(){
          console.log('reject-2');
       }
    );
    
[/code]

では、この場合はどうでしょう？  
最初に作成したPromiseはresolveなので、'resolve-1'が表示されます。  
しかし、この関数は例外が発生するので、次のPromseはrejectされ'reject-2'が表示されます。

このように、Promiseは次々と新しいPromiseが作成され順番に実行されます。

最後に、rejection関数を指定せず、途中で例外が発生した場合は、rejection関数を指定したPromiseまで飛ばされるので注意してください。

[code]

    new Promise(function (resolve, reject) {
       resolve('テスト');
    }).then(
        function(){
           console.log('resolve-1');
           throw 'resolve-error'; // 例外が発生したけど、次のthenで第2引数を設定していない・・・どうなる？
        }
     ).then(
        function(){
           console.log('resolve-2');
        }
     ).then(
        function(){
           console.log('resolve-3');
        },
         function(){
           console.log('reject-3');
         }
     ).then(
        function(){
           console.log('resolve-4');
        },
        function(){
          console.log('reject-4');
        }
     );
    
[/code]


CC BY-SA 3.0
2015-11-26T23:08:29.747
19346
2015-11-27T12:00:15.880
2015-11-27T12:00:15.880
4191
4191
19345
answer


まずは下記の検証用スクリプトとその実行結果を御覧ください。実行結果は nodejs v4.2.1 によるものです。

**検証用スクリプト**

[code]

    "use strict";
    
    var obj = new Promise(function(resolve, reject) {
      console.log("CHECK#1: in promise")
      reject("test");
    });
    console.log("CHECK#2: promise is created");
    
    var obj2 = obj.catch(function(e) {
      console.log("CHECK#3: in catch");
    });
    console.log("CHECK#4: after catch");
    
    console.log('obj:', obj);
    console.log('obj2:', obj2);
    
[/code]

**実行結果**

[code]

    CHECK#1: in promise
    CHECK#2: promise is created
    CHECK#4: after catch
    obj: Promise { <rejected> 'test' }
    obj2: Promise { <pending> }
    CHECK#3: in catch
    
[/code]

この結果から読み取れるように、`console.log(obj)` した時点では `new Promise()`
が返したPromiseは実行済みですが、`obj.catch()` が返したPromise(`obj2`)は未実行です。

質問内のコード2と3は、いずれも `obj2` に相当するPromiseを見ているので、pendingのままになっていると推測されます。対してコード1は
`obj` のPromiseを見ているのでrejected になります。

上記検証用スクリプトにおいて、`obj2` が pending ではなくなる = `catch` に渡した関数が実行されるのは、`obj2`
まで出力した後になっていますから、おそらくキューに蓄えられて、いわゆる `process.nextTick()`
に相当するタイミングで実行されていると考えられます。

### 参考

  * [そうだったのか！ よくわかる process.nextTick() node.jsのイベントループを理解する](http://www.slideshare.net/shigeki_ohtsu/processnext-tick-nodejs)


CC BY-SA 3.0
2015-11-27T00:36:12.750
19352
2015-11-27T00:36:12.750
208
19345
answer