2016-09-21 9 views
0

sendToSocketが成功した場合、setTimeoutdef.rejectのコードが実行されないのはなぜですか?コメントが言ったようにsendToSocketが成功した場合にsetTimeout def.rejectコードが実行されないのはなぜですか?

this.send = function(type, body) { 
    var def = Promise.defer(); 
    try{ 
     sendToSocket({...}); 
     setTimeout(function() { // if the send sendToSocket Succeeds how does nodejs/javascript know not to run the timeout code after 10 seconds? 
      def.reject(new Error("timeout")); 
     }, 10000); 
    }catch(err){ 
     logger.error('error'); 
     def.reject(err); 
    } 

    return def.promise; 
}; 
+2

プロミスは一度しか解決できません(この場合、「解決」という用語は「成功」または「間違い」を意味するために使用しています)...一旦解決すれば、拒否または実行しようとする試みは黙って無視されます。タイムアウト**は常に完了まで続きます**しかし、Promiseが既に完了している場合、拒否はPromiseには効きません - 仕様書のセクション2.1を読んでください - https://promisesaplus.com/ –

+0

@JaromandaX 'setTimeout'内の' def.reject'の直前に 'log'コマンドを実行すると、sendToSocketが正常に終了してから10秒が経過する前に' log'が実行されます。これは実行できない理由です。 – Jas

+0

'もしdef.rejectの直前にいくつかのログ印刷を追加したらどうでしょうか?setTimeout' - これを実行して見てください - –

答えて

2

、約束の状態は唯一の保留中の充足または拒否のいずれかに、一度に変更することができます。約束が履行されたら、その拒絶は無視されます。

また、それはより良い形と考えられていない使用Promise.defer()、代わりにnew Promiseのコンストラクタを使用します。

return new Promise(function(resolve, reject) { 
    sendToSocket({...}); // call resolve() here 
    setTimeout(function() { reject(new Error("timeout")); }, 10000) 
}); 

あなたが約束コンストラクタ内、いずれかがスローされたので、それはだ、ここにはtry/catchはありませんことに気づくでしょう例外は自動的に拒否に変換されます。


私はどうしたらもう事は、タイムアウトとは別の方法であり、このような何か:

function withTimeout(delay, fn) { 
    return function() { 
     return Promise.race([ // race between... 
      // Promise that rejects after "delay" ms 
      new Promise(function(resolve, reject) { 
       setTimeout(function() { reject(new Error("timeout")); }, delay); 
      }), // and... 
      // Promise that actually does the action 

      // The call to `Promise.resolve()` is to ensure we get a Promise 
      // even if the function doesn't return one. 
      Promise.resolve(fn.apply(null, arguments)) 
     ]); 
    }; 
} 

this.send = function() { 
    return new Promise(function(resolve, reject) { 
     sendToSocket({...}); // call resolve here, or reject on error. 
          // thrown errors will be converted anyway 
    }); 
}; 

this.sendWithTimeout = withTimeout(10000, this.send.bind(this)); 

withTimeoutはとの約束を返す新しい機能を返します呼び出しますタイムアウトオプション。

Promise.race()は、渡されたPromiseの配列から最初のPromiseが解決または拒否されたときに解決する(または拒否する)Promiseを返します。我々はレーシングの間に実際の約束はthis.send()から返され、タイムアウト時に拒否する約束です。

これは、あなたのthis.send()関数が実際に送信するだけのことを意味します。タイムアウトは、抽象化によって追加する詳細です。

+0

nice! '.race'について知らなかった! – Jas

関連する問題