2016-04-22 12 views
0

なぜ、ネイティブプロミスは構文エラーに関してtry/catchのように振る舞うのですか?あなたが順序で非同期操作の数を実行する必要がある場合プロミスが構文エラーをキャプチャするのはなぜですか?

約束は明らかに、フローコントロールの値を持っています。しかし、すべての約束のためにあなた自身の不適切なエラー・インプリメンテーションを実装する必要があると、時にはそれを扱う手間がかかります。

は、次のコードを取る:

asdf 
 

 
let one = new Promise((resolve, reject) => { 
 
    asdf 
 
}).catch(err => { 
 
    console.log(err) 
 
    console.log(err.stack) 
 
})

最初の構文エラーは、一般的なブラウザのエラーと18のエントリでスタックトレースを生成します。 promise'dバージョンは4です。

私の質問は、仕様書を作成してネイティブに実装するとき、ユーザー空間実装の約束のようなtry/catchのような機能を、フローに使用できるように保持していた理由です標準的なエラー処理を残しますか?

+3

それは構文エラーはありませんが、将来的に参照エラー(おそらく)occuringので。 – Bergi

+1

エラーは、SyntaxErrorsではなくReferenceErrorsであることに注意してください。後者は、エンジンがスクリプトを実行するのに十分理解できないため、捕まえられません。しかし、 'asdf'は有効な識別子であり、変数へのアクセスだけが有効なステートメントです。したがって、パーサーはそれに問題はないと判断します。 –

+0

これが適切な複製であるかどうかは不明です。[なぜJSで約束を拒否するために例外が使用されるのですか?](http://stackoverflow.com/q/21616432/1048572) – Bergi

答えて

3

実際の構文エラーが時にコードをロードJavascriptのパーサーによってスローされますと、まだスローされる例外となります。基本的に、パーサーがコードを正しく解析できないと判断した場合、その時点で何もする必要はありません。それはあきらめて残りのコードの解析を停止します。

これは、処理する約束ランタイムエラー(つまり、コード実行中でないロード/構文解析中に発生する)です。仕様で

.then()約束ハンドラは、彼らが拒否された約束にスローされた例外を回すことを意味している「安全投げる」です。これらのハンドラは、非同期コールバックで非同期とスローされた例外は常に呼び出し元のコードは、もはやスタック上で、呼び出し元のコードが唯一のコールバックを介して通知することができますので、それらは、呼び出し元のコードでキャッチすることはできませんので、かなり役に立たないので、これが行われます。例外は、呼び出しコードがそれらを傍受または処理できる非同期インフラストラクチャに移行するだけです。そこで、例外を拒否にする決定を下したので、通常の拒否処理とエラーの伝播がすべて使用できるようになりました。

そして、約束がこれをしなかった場合には、例外をキャッチすることができないので、あなたが何かを捕まえることを確かめるためにほとんどすべての.then()ハンドラで自分のtry/catchを行う必要があります間違っている。したがって、余分なコードが大幅に節約され、すべての非同期例外が適切に捕捉され、エラーが呼び出しコードに戻されることを確実にすることが容易になります。

一言で言えば、それに慣れてしまえば、それは信じられないほど便利で、どこにも例外はありませんので、デザイナーは例外をキャッチして有用にすることで非常に良い選択をしたと言います。参考までに、.then()ハンドラの中で、いつでも自分のtry/catchを実行して、必要に応じて自分の好きなことをすることができます。

0

理由は、非同期プロセスを扱うときに、nobodyがエラーを捕らえるためです。 前のコールスタックがなくなっています。ウィットに

function simulateAsyncError() { 
    try { 
    setTimeout(function() { throw new Error("Nobody caught me"); }, 1); 
    console.log("I have set the future error."); 
    } catch (err) { console.log("I caught it!"); } 
} 

simulateAsyncError(); 
// "I have set the future error." 
// Uncaught Error: "Nobody caught me" 

約束はそれをラップし、それに対処するとしています。

+0

例は完全に元の投稿の下部に提起された質問に答えるので、私は完全にdownvoteで混乱しています。 – Norguard

1

約束は、構文解析/コンパイル時に発生する典型的な構文エラーをキャプチャしません。あなたの例はSyntaxErrorではありません(パーザはあなたのコードを理解しません)、それはReferenceErrorです(インタプリタ/ランタイムはあなたが指定した識別子を見つけることができません)。

Uncaught ReferenceError: asdf is not defined 

構文エラーがリテラルコードであった場合、それは、ないがキャッチされていたであろう。これは私たちが期待するべきことです。コードを解析できなければ、あなたが約束を作ったことさえ知ることができません。

let one = new Promise((resolve, reject) => { 
    foo bar baz 
}).catch(err => { 
    // ignore error 
}); 
Uncaught SyntaxError: Unexpected identifier 

あなたは(約束-使用したコードの観点から)実行時で構文エラーを生成するevalを使用する場合、それがキャッチされることに注意してください。その違いは、JavaScriptオブジェクト型のエラーの違いではなく、コンパイル時と実行時のエラーの区別です。

let one = new Promise((resolve, reject) => { 
    eval("foo bar baz"); 
}).catch(err => { 
    console.log("Captured error:", err); 
}) 
Captured error: SyntaxError: Unexpected identifier 
関連する問題