2017-09-19 13 views
0

私のコントローラは、長時間実行されている約束を一時停止、再開、解決することができます。 私のコントローラがPromiseを打ち切ると、どういうわけか私のコントローラ再帰ループが壊れています。長時間の約束を一時停止、再開、中止、解決

私は数日前にプロミスについて学んだので、拒否やキャッチについて何か分かりません。

まず、promise chainのステップ間でチェックインできる状態変数。この状態をチェックするために挿入することができます

var state = "idle" 

シム約束変数

// insert this shim before each link of promise chain 
function promise_to_check_pause_and_abort(x) { 
    if (state == "running") { 
     return Promise.resolve(x) // just keep going 
    } else if (state == "pause") { 
     let P = new Promise((resolve, reject) => { 
      let resume_cb =() => { resolve() } 
      pause_cb_queue.push(resume_cb) 
     }); 
     return P; 
    } else if (state == "abort") { 
     return Promise.reject("aborted at stage " + x) 
    } else { 
     return promise.reject("should not be executing in this invalid state = " + state) 
    } 
} 

は私の本当のアプリケーションが完了するまでに15+分かかることがあり、多くのチェーンの約束を実行します。これは私の問題を実証するためには必要ありません。だから、約束を返す単純な偽の仕事があります。

function promise_to_do_something_long_running(n) { 
    if (isNaN(n)) { 
     n = 0; 
    } 

    if (n == 100) { 
     return Promise.resolve("done") 

    } else { 
     let P = new Promise((resolve, reject) => { 
      setTimeout(() => { 
       console.log("doing " + n); 
       resolve(); 
      }, 100) 
     }) 

     return P 
      .then(() => { return promise_to_check_pause_and_abort(n) }) 
      .then(() => { return promise_to_do_something_long_running(n + 1) }) 
    } 

} 

これで、上記の長時間の約束を開始、一時停止、再開、中止する簡単なテキストコントローラです。

// A recursive controller. 
// Get response based on current running state. 
// Regardless of response, do it again. 
function controller() { 

    if (state == "running") { 
     rl.question("abort or pause :", (answer) => { 

      if (answer == "abort") { 
       state = "abort" 
      } else if (answer == "pause") { 
       state = "pause" 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 

    } else if (state == "pause") { 
     rl.question("abort or resume :", (answer) => { 

      if (answer == "abort") { 
       state = "abort"; 
       pause_cb_queue.forEach((cb) => { cb() }) 
       pause_cb_queue = [] 
      } else if (answer == "resume") { 
       state = "running" 
       pause_cb_queue.forEach((cb) => { cb() }) 
       pause_cb_queue = [] 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 

    } else if (state == "idle") { 

     rl.question("start :", (answer) => { 

      if (answer == "start") { 
       state = "running"; 

       // controller loop not dependent on resolution of this 
       // only state is 
       promise_to_do_something_long_running() 
        .then((a) => { 
         console.log("completed task, response :" + a); 
         state = "idle" 
        }) 
        .catch((b) => { 
         console.log("task rejected with response :" + b); 
         state = "idle" 
        }); 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 
    } 

} 


controller(); 

すべてが、私は、中止コントローラ再帰休憩時を除いて、完璧に動作し、それ以上の入力は、ユーザから募集されていません。どのように

.catch((b) => { 
         console.log("task rejected with response :" + b); 
         state = "idle" 
        }); 

の実行は、外側のコントローラ再帰を停止させることができますか?次のように

nodejsで実行される完全なコードではありません。約束を一時停止し、再開と間違っ

'use strict'; 


const readline = require('readline'); 

const rl = readline.createInterface({ 
    input: process.stdin, 
    output: process.stdout 
}); 

var state = "idle" 
var pause_cb_queue = [] 


// insert this shim before each link of promise chain 
function promise_to_check_pause_and_abort(x) { 
    if (state == "running") { 
     return Promise.resolve(x) // just keep going 
    } else if (state == "pause") { 
     let P = new Promise((resolve, reject) => { 
      let resume_cb =() => { resolve() } 
      pause_cb_queue.push(resume_cb) 
     }); 
     return P; 
    } else if (state == "abort") { 
     return Promise.reject("aborted at stage " + x) 
    } else { 
     return promise.reject("should not be executing in this invalid state = " + state) 
    } 
} 

function promise_to_do_something_long_running(n) { 
    if (isNaN(n)) { 
     n = 0; 
    } 

    if (n == 100) { 
     return Promise.resolve("done") 

    } else { 
     let P = new Promise((resolve, reject) => { 
      setTimeout(() => { 
       console.log("doing " + n); 
       resolve(); 
      }, 100) 
     }) 

     return P 
      .then(() => { return promise_to_check_pause_and_abort(n) }) 
      .then(() => { return promise_to_do_something_long_running(n + 1) }) 
    } 

} 

// A recursive controller. 
// Get response based on current running state. 
// Regardless of response, do it again. 
function controller() { 

    if (state == "running") { 
     rl.question("abort or pause :", (answer) => { 

      if (answer == "abort") { 
       state = "abort" 
      } else if (answer == "pause") { 
       state = "pause" 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 

    } else if (state == "pause") { 
     rl.question("abort or resume :", (answer) => { 

      if (answer == "abort") { 
       state = "abort"; 
       pause_cb_queue.forEach((cb) => { cb() }) 
       pause_cb_queue = [] 
      } else if (answer == "resume") { 
       state = "running" 
       pause_cb_queue.forEach((cb) => { cb() }) 
       pause_cb_queue = [] 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 

    } else if (state == "idle") { 

     rl.question("start :", (answer) => { 

      if (answer == "start") { 
       state = "running"; 

       // controller loop not dependent on resolution of this 
       // only state is 
       promise_to_do_something_long_running() 
        .then((a) => { 
         console.log("completed task, response :" + a); 
         state = "idle" 
        }) 
        .catch((b) => { 
         console.log("task rejected with response :" + b); 
         state = "idle" 
        }); 
      }; 

      controller(); // regardless of response or state, get input again 
     }) 
    } 

} 


controller(); 

答えて

1

は何も。私のバグはコントローラーの中断状態を処理していませんでした。

} else if (state == "abort") { 
     rl.question("in abort state, no valid input :", (answer) => { 
      controller(); // regardless of response or state, get input again 
     }) 

上記を加えれば、すべてが完全に機能します。今私は約束を中断することができます。

関連する問題