Обработка ошибок в рекурсивной функции setTimeout в Node.js

Я создаю свое первое приложение node.js на моем Raspberry Pi, которое я использую для управления кондиционером через LIRC. Следующий код вызывается, когда вы хотите увеличить температуру блока переменного тока. Он отправляет команду LIRC каждые 250 миллисекунд в зависимости от того, на сколько градусов вы хотите увеличить ее. Этот код работает как положено.

var iDegrees = 5;
var i = 0;
var delay = 250 // The delay in milliseconds

function increaseTemperatureLoop(){
    i++;        
    //lirc_node.irsend.send_once("ac", "INCREASE", function() {});
    console.log(i);

    // Call the fucntion/loop again after the delay if we still need to increase the temperature
    if (i <= iDegrees){
        timer = setTimeout(increaseTemperatureLoop, delay);
    }
    else {
        res.json({"message": "Success"});
    }
}

// Start the timer to call the recursive function for the first time
var timer = setTimeout(increaseTemperatureLoop, delay);

Мне трудно работать с асинхронной природой node.js. Когда моя рекурсивная функция завершена, я возвращаю свой json в браузер, как показано в коде выше. По привычке я чувствую, что должен возвращать json в строке кода после моего первоначального вызова функции, как показано ниже, но очевидно, что он не будет ждать, пока все вызовы LIRC будут успешными - кажется глупым иметь его внутри функции:

var timer = setTimeout(increaseTemperatureLoop, delay);
res.json({"message": "Success"});

Что если у меня есть куча других вещей, которые нужно сделать после того, как мои отправки LIRC будут выполнены, но прежде чем я захочу отправить свой json обратно в браузер? Или что, если этот блок кода выдает ошибку...

Мой второй вопрос: как правильно обернуть вызов LIRC в try/catch, а затем, если есть ошибка, прекратить рекурсивные вызовы, передать ошибку обратно, а затем передать ее обратно в браузер вместе с фактической ошибкой сообщение:

res.json({"message": "Failed"});

1 ответ

  1. Для отслеживания конца цикла выполнения задачи вы можете использовать обратный вызов.
  2. Чтобы узнать, завершены ли все рутинные задачи, вы можете использовать очередь задач.
  3. Отслеживать и сообщать об ошибках наверх - это возможно с помощью трех одинаковых обратных вызовов.
  4. В общем, желательно обернуть все в один объект.

Некоторый пример для размышления:

var lircTasks = function __self (){

    if (typeof __self.tasks === "undefined") __self.tasks = 0;

    __self.func = {
        increaseTemperature: function() {
                // lirc_node.irsend.send_once("ac", "INCREASE_TEMPERATURE", function() {}); 
        },
        increaseFanPower: function() {
                // lirc_node.irsend.send_once("ac", "INCREASE_FANPOWER", function() {});
        }
    }

    var fab = function () {

        __self.tasks++;
        this.i = 0;
        this.args = arguments[0];
        this.callback = arguments[1];

        this.run = function __ref(taskName) {
            if (taskName) this.taskName = taskName;
            if (this.i<this.args.deg) {
                try {
                    __self.func[this.taskName]();
                } catch(e) {
                    __self.tasks--;
                    this.callback( {message: "error", error: e, taskName: this.taskName, task: this.args, tasks: __self.tasks} );
                }
                this.i++;
                setTimeout( __ref.bind(this), this.args.delay );
            } else {
                __self.tasks--;
                this.callback({message:"complete", taskName: this.taskName, task: this.args, tasks: __self.tasks});
            }
        }

    }

    if ((arguments.length === 2) && (typeof arguments[1] === "function") && arguments[0].deg>0 && arguments[0].delay>=0) {
        return new fab(arguments[0], arguments[1]);
    }

}

function complete(e) {
    console.log(e);
    if (e.tasks === 0) console.log({message: "Success"});
}

lircTasks( {deg: 10, delay:100, device: "d1" }, complete ).run("increaseTemperature");
lircTasks( {deg: 20, delay:150, device: "d2" }, complete ).run("increaseTemperature");
lircTasks( {deg: 5, delay:100, device: "d3" }, complete ).run("increaseFanPower");
Другие вопросы по тегам