暂停,简历,中止和决心长期承诺



我的控制器能够暂停,恢复和解决长期的承诺。当我的控制器中止诺言时,我的控制器递归循环被打破了。

我几天前就学会了诺言,所以也许我不了解有关拒绝或捕获的东西。

首先,可以在前景链之间进行检查的状态变量。

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();

暂停和恢复承诺没有错。我的错误缺少在控制器中处理中止状态。

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

随着上述添加,一切正常。我现在可以暂停承诺链。

最新更新