2016-04-25 11 views
0

私はタイトルの第4章を読んでいます「あなたは知らないJS:ES6 &を越えて」 私はPromise.resolve(..)この静的関数にthenableまたは即値を渡すときに何が起こるかを知っています。 しかし、どのような場合、それはそのPromise.resolve(it.throw(err))に行きますか?どのようPromise.resolve(it.throw(ERR))。その後、(handleResult)を理解するには?

のような約束+ジェネレータパタパタ示し全体コード: - 約束のチェーンがいっている場合function handleErr(err){..} がどのように動作し、何が起こるでしょう

function run(gen) { 
    var args = [].slice.call(arguments, 1), it; 

    it = gen.apply(this, args); 

    return Promise.resolve() 
     .then(function handleNext(value){ 
      var next = it.next(value); 

      return (function handleResult(next){ 
       if (next.done) { 
        return next.value; 
       } 
       else { 
        return Promise.resolve(next.value) 
         .then(
          handleNext, 
          function handleErr(err) { 
           return Promise.resolve(
            it.throw(err) 
           ) 
           .then(handleResult); 
          } 
         ); 
       } 
      })(next); 
     }); 
} 

私の主な問題は拒否ハンドラです。

+0

'it'ジェネレータが' catch'ステートメントから 'yield'する場合です。確かに、 'return handleResult(it.throw(err))'だったはずです。そこに 'Promise.resolve' /' then'を置く必要はありません。 – Bergi

+0

@Bergi - そこに置くことは絶対に重要です。それは意図的なものであり、間違いではありません。 'handleResult(it.throw(err)) 'を呼び出すと、今度はこのティックの間に呼び出されますが、私たちはそれを望んでいません。次のティックでそれを望みます。なぜなら、' Promise.resolve'でラップされ、 '.then'で次のティックに移動します。 –

+0

@KyleSimpson:コルーチンはダニについて本当に気にしますか?しかし、たとえそれがあったとしても、handleResultに関係なく、ジェネレータを前進させる 'handleNext' /' handleErr'はどんな場合でも非同期に呼び出されます。 – Bergi

答えて

2

しかし、それに行くとどうすればPromise.resolve(it.throw(err))

it.throw(..)の結果はIteratorResultオブジェクトである:{ value: .., done: true }it.next(..)からようちょうど同じ。 .then(handleResult)は、次のティックにを実行したとき、そのオブジェクトの値はhandleResult(..)に戻されるので、私は、Promise.resolve(..)と約束してアップオブジェクトラッピングです。

return handleResult(it.throw(err))を@Bergiのコメントで示唆されているように実行する理由は、このチックでhandleResult(..)を実行するためです(コールスタックの目的ではありません)。

function handleErr(err){..}これはどのように機能し、約束が続くかどうかはどうなりますか? (Promise.resolve(next.value)経由で持ち上げられ)​​は、最終的に拒否された約束である場合

handleErr(..)だけと呼ばれています。例えばだから:

run(function*(){ 
    yield Promise.reject(42); 
}); 

ここで、拒否約束は​​であるのでPromise.resolve(next.value)だけ拒否約束として、それを維持し、かつthen(handleNext,handleErr)原因handleErr(..)が拒否42値で呼び出されるように、最初のit.next(..)呼び出しから戻って来ました。

は今、it.throw(err)は、発電機の内部でtry..catchを待って、それをキャプチャするだろういくつかの場合には、戻って発電機に、この例外値(42)をスローするようにしようとします。例えば

、私たちの発電機はこのように、try..catchを持っていなかった場合:その後、42例外がキャッチされるだろうし、その後return 10が起こる...

run(function*(){ 
    try { 
     yield Promise.reject(42); 
    } 
    catch (err) { 
     return 10; 
    } 
}); 

。したがって、it.throw(..)呼び出しが{ value: 10, done: true }で正常に戻るだろう。

さて、Promise.resolve(..)は通常満たさ約束にそれを持ち上げるだろう、とhandleResult(..)はそのnextパラメータとして、そのオブジェクトと、次のティックで、呼び出されます。if (next.done)がパスし、return next.value10を返します。これは、再帰的なプロミスチェーンを通じて返され、最終的にrun(..)への元の呼び出しが返されたという最も外側の約束で解決されます。当社独自の発電機がないをやったので、

しかし、it.throw(next.value)が発生したときに、それがで投げた例外は、異常電流のhandleErr(..)呼び出しを中止した、出てすぐに戻ってくる、try..catchを持っています。 handleErr(..)then(..)によって開始されているので、then(..)はその例外を拒否された約束にリフトし、再帰的約束チェーンを通じて返され、最終的にrun(..)への呼び出しが返されたという最も外側の約束を拒絶します。