3

我有開始在的NodeJS一些後臺作業(作業是HTTP請求),此模塊是它的一個簡化版本:的NodeJS後臺作業從不執行,一直循環下去

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的模塊,但我不知道這是否適用於此處或者有多穩定(似乎不是活動項目)。我可以嘗試,但在繼續之前我仍然想了解這個問題。

回答

1

問題是node.js是單線程的。 While循環繼續運行並佔據事件循環,因此setTimeout沒有機會觸發。而不是一個while循環來開始工作,你會想要把它放在setInterval(或可能是遞歸的setTimeout)。例如:

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'); 
}); 
+0

謝謝,它的工作原理。如果你不介意,我可以問一個後續問題,它是否在編寫'setTimeout(function(){mirror.start()},50);''''setTimeout(mirror.start,50) ;'? – Dreen

+1

@ user0000001第二種方法會調用正確的方法,但是'this'將是全局的,而不是您期望的。 –