私のコントローラは、長時間実行されている約束を一時停止、再開、解決することができます。 私のコントローラが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();