javascript - 在 NodeJs Promise while 循环中停止多个服务 Controller 查询

标签 javascript node.js promise gulp service-control-manager

我正在尝试从 Node 脚本启动 Windows 服务。该服务有挂起的坏习惯,有时需要重试才能成功启动。我有一个 promise while 循环设置(请随时提出更好的方法)。我遇到的问题是,每个循环的 sc.pollInterval 输出都会在控制台中写入重复的结果。下面是我在控制台中看到的重复内容的示例,这是在循环中的第二次迭代之后,我希望它只显示该内容一次。

sc \\abnf34873 start ColdFusion 10 Application Server

sc \\abnf34873 queryex ColdFusion 10 Application Server

SERVICE_NAME: ColdFusion 10 Application Server
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 0
        FLAGS              :

SERVICE_NAME: ColdFusion 10 Application Server
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 13772
        FLAGS              :

这是我的代码。基本上,我会尝试启动该服务 3 次。如果没有,那么我会抛出错误。需要注意的一件事是,当我尝试启动服务,但它陷入“Start_pending”状态时,我会终止该进程,然后尝试再次启动它。

var retryCount = 0;

// Start the colfusion service
gulp.task('start-coldfusion-service', function(done) {
    var serviceStarted = false;
    console.log("Starting coldfusion service..");
    // This says we're going to ask where it's at every 30 seconds until it's in the desired state.
    sc.pollInterval(30);
    sc.timeout(60);
    retryCount = 0;

    tryServiceStart().then(function(result) {
          // process final result here
        done();
    }).catch(function(err) {
        // process error here
    });
});


function tryServiceStart() {
    return startService().then(function(serviceStarted) {
        if (serviceStarted == false) {
            console.log("Retry Count: " + retryCount);
            // Try again..
            return tryServiceStart();
        } else {
             return result;
        }
    });
}

function startService() {
    return new Promise(function(resolve, reject) {
        var started = true;
        // Make sure the coldfusion service exists on the target server
        sc.query(targetServer, { name: 'ColdFusion 10 Application Server'}).done(function(services) {
            // if the service exists and it is currentl stopped, then we're going to start it.
            if (services.length == 1) {
                var pid = services[0].pid;
                if (services[0].state.name == 'STOPPED') {
                    sc.start(targetServer, 'ColdFusion 10 Application Server')
                        .catch(function(error) {
                            started = false;
                            console.log("Problem starting Coldfusion service! error message: " + error.message);
                            console.log("retrying...");
                            retryCount++;
                            if (parseInt(retryCount) > 2) {
                                throw Error(error.message);
                            }
                       })
                       .done(function(displayName) {
                            if (started) {
                                console.log('Coldfusion service started successfully!');
                            }
                            resolve(started);
                       });
                } else if (services[0].state.name == 'START_PENDING') {
                    kill(pid, {force: true}).catch(function (err) {
                        console.log('Problem killing process..');
                    }).then(function() {
                        console.log('Killed hanging process..');
                        resolve(false);
                    });
                }
            } else {
                console.log("Could not find the service in a stopped state.");
                resolve(false);
            }
        });
   });
}

最佳答案

不太清楚为什么你会在控制台中得到重复的结果,但是下面是一些关于如何更好地编写代码的想法,主要是通过在最低级别进行 promise 。

非常接近最初的概念,我最终得到了这个......

Promisify sc 命令

  • sc 命令返回类似于 Promise 的内容,但使用 .done() 方法,该方法很可能不具备真正的 .then() 的全部功能
  • 将每个命令 promise 为 .xxxAsync()
  • 通过采用每个命令的 .done 作为 .then,Promise.resolve() 应该能够同化命令返回的类似 Promise 的东西。
;(function() {
    commands.forEach(command => {
        sc[command].then = sc[command].done;
        sc[command + 'Async'] = function() {
            return Promise.resolve(sc[command](...arguments)); 
        };
    }).
}(['start', 'query'])); // add other commands as required

gulp.task()

  • 如果服务打开,promise 链遵循其成功路径,否则其错误路径
  • 无需测试结果来检测成功路径中的错误情况。
gulp.task('start-coldfusion-service', function(done) {
    console.log('Starting coldfusion service..');
    // This says we're going to ask where it's at every 30 seconds until it's in the desired state.
    sc.pollInterval(30);
    sc.timeout(60);
    tryServiceStart(2) // tryServiceStart(maxRetries)
    .then(done) // success! The service was started.
    .catch(function(err) {
        // the only error to end up here should be 'Maximum tries reached'.
        console.err(err);
        // process error here if necessary
    });
});

tryServiceStart()

  • 在此处协调重试
function tryServiceStart(maxRetries) {
    return startService()
    // .then(() => {}) // success! No action required here, just stay on the success path.
    .catch((error) => {
        // all throws from startService() end up here
        console.error(error); // log intermediate/final error
        if(--maxRetries > 0) {
            return tryServiceStart();
        } else {
            throw new Error('Maximum tries reached');
        }
    });
}

startService()

  • 通过调用 sc.query()sc.start() 的 Promisified 版本形成功能齐全的 Promise 链
  • console.log() 已被清除以支持抛出。
  • 抛出的错误将被捕获并记录回 tryServiceStart()
function startService() {
    // Make sure the coldfusion service exists on the target server
    return sc.queryAsync(targetServer, { name: 'ColdFusion 10 Application Server'})
    .then((services) => {
        // if the service exists and it is currently stopped, then start it.
        if (services.length == 1) {
            switch(services[0].state.name) {
                case 'STOPPED':
                    return sc.startAsync(targetServer, 'ColdFusion 10 Application Server')
                    .catch((error) => {
                        throw new Error("Problem starting Coldfusion service! error message: " + error.message);
                    });
                break;
                case 'START_PENDING':
                    return kill(services[0].pid, { 'force': true })
                    .then(() => {
                        throw new Error('Killed hanging process..'); // successful kill but still an error as far as startService() is concerned.
                    })
                    .catch((err) => {
                        throw new Error('Problem killing process..');
                    });
                break;
                default:
                    throw new Error("Service not in a stopped state.");
            }
        } else {
            throw new Error('Could not find the service.');
        }
    });
}

仅检查语法错误,因此很可能需要调试。

提供 FWIW。请随意酌情采用/突袭。

关于javascript - 在 NodeJs Promise while 循环中停止多个服务 Controller 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48301846/

相关文章:

javascript - AngularJS:指令与 Controller - 什么逻辑放在哪里?

javascript - 在 Twitter Bootstrap 中,我如何阻止所有 Accordion 在页面加载时瞬间展开?

javascript - 将索引器传递到回调中的问题

javascript - 包装 javascript fetch 以添加自定义功能

javascript - 无法使用 .removeItem 删除 LocalStorage 项目

angularjs - 错误 : Cannot find module 'js-yaml' when running "bower install"

windows - Windows 上的 Nodejitsu

javascript - 如何创建 promise 循环

javascript - Promise 输出因 NodeJs 和浏览器而异

javascript - 无法得到我在 nodejs/mongoose/bluebird 中返回的 promise