2017-01-09 5 views
-2

問題をキャンセルするか約束半ば実行無視して、実行時に別のものと交換していることが唯一のそれは現在の状態がありますので、約束JS約束未定義の動作

をキャンセルする必要が、それは可能です解決しますか?

生産コードでは、私はcancel()メソッドを定義する角$timeoutを使用しています。

//Mimic AngularJS's $timeout 
function MyTimeout(delay) { 
    var t = null; 
    var p = new Promise(function (resolve) { 
     t = setTimeout(resolve, delay); 
    }); 
    p.realtimeout = t; 
    return p; 
} 
MyTimeout.cancel = function (myto) { 
    clearTimeout(myto.realtimeout); 
    /* 
    * there is no way to appropriately cancel an existing Promise 
    * the best I can do in try and change the state of myto to a rejected 
    * Promise. Which doesn't help here since it doesn't truly cancel the last 
    * Promise... 
    */ 
    myto = Promise.reject("some reason"); 
}; 


var x = null; 

function changeState() { 
    var delay; 

    if (x === null) { 
     delay = 1000; 
    } else { 
     MyTimeout.cancel(x); 
     delay = 3000; 
    } 

    x = MyTimeout(delay).then(print_delay); 

    function print_delay() { 
     console.log("EXECUTED: %s", delay); 
    } 
} 


changeState(); 

x.then(function() { 
    console.log("DONE"); 
}).catch(console.error); 

changeState(); 

NodeJS出力を

(node:12461) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): some reason 
(node:12461) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 

EXECUTED: 1000 
DONE 
EXECUTED: 3000 

アウトカム予想:EXECUTED: 3000は、一度印刷してくださいあなたはノードで実行することができますので、私はここに模倣-ED、それを持っています。フラグが設定されているので、それに応じてxが設定されているためです。 xは、その実行コンテキストを指している必要があります。

+0

はあなたが少しを提供することができます:/ resolveが呼び出されたかときに後から変更することができるようにあなたが既に持っている約束の解決プロセスに影響を与える必要があり、そのためにあなたが方法でそれを作成する必要がありますあなたが達成しようとしていることについてより多くの文脈?それは、これを解決する最善の方法を理解するのに役立ちます。 –

+0

約束は一度解決されます。おそらく私は間違っていますが、あなたは2つの約束を使用し、最初に解決された約束を聞くために 'Promise.race'を使用することができます。あなたはまた、最初の約束を拒否するためにいくつかの論理的な不合理を必要とします。 –

+0

* "' .then() 'は2回呼び出されます。" '.then'は一つの約束にのみ付随しています。 'mypromise'に新しい約束を作成して割り当てても、前の約束からすべてのコールバックを魔法のように動かすことはありません。あなたが 'strangeFunc()'を呼び出した後、あなたは未だ約束をしています。 –

答えて

1

mypromiseまたはxを既に使用した後は、変数参照を変更しても最初の約束事およびそのハンドラには全く影響しないため、交換することはできません。

function variableDelay(x) { 
    var timer = 0; 
    var end; 
    return { 
     promise: new Promise(resolve => { 
      end =() => { 
       timer = -1; 
       resolve(x); 
      }; 
     }), 
     setDelay(d) { 
      if (timer < 0) throw new Error("too late"); 
      if (timer > 0) clearTimeout(timer); 
      timer = setTimeout(end, d); 
      return this; 
     } 
    }; 
} 


const {promise:x, setDelay:changeState} = variableDelay(); 
changeState(1000); 
x.then(() => { 
    console.log("DONE"); 
}).catch(console.error); 
changeState(3000); 
+0

最初のPromiseは引き続きresolve関数を実行しますが、コンテキストが変更された後にのみこの実行を延期する方法はありますか?また、 'new Promise'の') 'が欠けています – Rafael

+0

いいえ、約束は何も実行しません。' set'をスケジュールする 'setDelay'(' resolve'で)です。 – Bergi

+0

準備ができたら約束を解決する基本的なスケジューラ – Rafael

関連する問題