javascript - NodeJS 后台作业从不执行,永远循环

标签 javascript node.js asynchronous background-process job-scheduling

我有一个模块在 NodeJS 中启动一些后台作业(这些作业是 HTTP 请求),这是它的简化版本:

var
util    = require('util'),
EE  = require('events').EventEmitter,
Winston = require('winston');
var logger = new Winston.Logger({transports: [new Winston.transports.Console()]});

function Bot() {
    EE.call(this);
    this.model = ['job1','job2','job3'];
    // null = never had a job, false = job started, true = job finished
    this.jobs = {
        'job1': null,
        'job2': null,
        'job3': null };
    var mirror = this;

    function start_job(job) {
        var t = Math.floor(Math.random() * 10 + 1) * 1000;
        logger.info('calling ' + job + ' for t=' + t);
        setTimeout(function() {
            logger.info('finished ' + job);
            mirror.jobs[job] = true;
        }, t);
    }

    this.on('start', function() {
        logger.info('Starting');
        while (mirror.isRunning()) {
            for (var i=0; i<mirror.model.length; i++) {
                var job = mirror.model[i];
                var oldJob = mirror.jobs[job];
                if (oldJob === null || oldJob === true) {
                    mirror.jobs[job] = false;
                    start_job(job);
                }
            }
            // mirror.shutdown();
        }
        logger.info('Shutting down');
    });
}

util.inherits(Bot, EE);

Bot.prototype.shutdown = function() {
    this.running = false;
};
Bot.prototype.start = function() {
    this.running = true;
    this.emit('start');
};
Bot.prototype.isRunning = function() {
    return this.running;
};

var bot = new Bot();
bot.start();

问题是作业从未真正运行过。 start_job() 被调用,但 setTimeout() 中的 anon 函数从不触发。这是输出:

info: Starting
info: calling job1 for t=6000
info: calling job2 for t=5000
info: calling job3 for t=9000

脚本此时挂起,进入无限循环。

现在,如果我在第一次循环迭代后停止,通过取消注释 mirror.shutdown(),作业将按预期开始:

info: Starting
info: calling job1 for t=6000
info: calling job2 for t=9000
info: calling job3 for t=1000
info: Shutting down
info: finished job3
info: finished job1
info: finished job2

但是这样不好。我不知道为什么会这样,但我是 Node 的新手并且仍在为一些概念而苦苦挣扎。

我知道一个名为 Background.js 的模块,但我不知道这是否适用于此或它的稳定性如何(似乎不是一个活跃的项目)。我可以尝试一下,但我仍然想在继续之前了解这个问题。

最佳答案

问题是 node.js 是单线程的。 while 循环继续运行并占用事件循环,因此 setTimeout 没有机会触发。您需要将其放在 setInterval(或者可能是递归 setTimeout)上,而不是 while 循环来启 Action 业。例如:

this.on('start', function() {
    logger.info('Starting');
    for (var i=0; i<mirror.model.length; i++) {
        var job = mirror.model[i];
        var oldJob = mirror.jobs[job];
        if (oldJob === null || oldJob === true) {
            mirror.jobs[job] = false;
            start_job(job);
        }
    }
    setTimeout(function(){mirror.start()}, 50);
    logger.info('Shutting down');
});

关于javascript - NodeJS 后台作业从不执行,永远循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16564747/

相关文章:

node.js - 哪些 Google 域验证 API 用于 Pub/Sub 域验证?

python - 在 RequestHandler 写入的情况下 Yield 和 Await 的不同行为(Tornado Web Framework)

javascript - 正确捕获异步函数node.js

javascript - 从node.js发送请求到apache2.2.21

javascript - 元素及其父元素指定了 ng-click,两者都被称为

javascript - 如何使用 d3.js 获取垂直方向的树

node.js - 如何将角色添加到用户的证书并在链代码中使用它们?

mysql - 在创建带有迁移的表时设置外键约束 Sequelize

Android - 异步任务的替代方案?

javascript - 如何使用元素标签名称在 DOM 树中上下移动?