Обратный вызов Mongoose не работает с использованием Forever

Я пытаюсь запустить фоновый процесс с Forever, который каждый час добавляет данные из внешней службы в мою базу данных mongodb (я новичок в узле и понятия не имел, как это сделать). Я использую Node с Express и запускаю задачу навсегда, используя

forever -o out.log -e err.log start background/collector.js

так что у меня есть некоторые отзывы о процессе. Код следующий:

var request = require('request');
var mongoose = require('mongoose');
var Model = require('../models/Model.js');

// Starting the collector process
addNewData();

function addNewData() {
    request('external_service_url', function (error, response, body) {
        if (!error && response.statusCode == 200) {
            var models = JSON.parse(body);

            console.log('Adding the new models...')
            for(var i = 0; i < models.length; i++)
            {
                console.log(i);

                Model.create(models[i], function (error, post, result) {
                    console.log('Test');
                    if (error) console.log('Something went wrong adding the document!');
                    if ( ! result.updatedExisting)
                    {
                        console.log('A new document has been added!');
                    }
                });
            }

            console.log('Models added: ' + models.length);

            // Every hour we will collect new data

            console.log('Waiting for an hour...');
            setTimeout(addNewData, 36000000);
        }
    })
}   

Я не знаю почему, но кажется, что обратный вызов .create() не работает, console.logs, помещенные внутри обратного вызова create, ничего не показывают в журналах. Навсегда не работает с мангустом? У вас есть идея?


person miquelarranz    schedule 11.07.2015    source источник


Ответы (1)


Ну вот в чем дело. Вы никогда не «подключали» свой адаптер мангуста к базе данных. Просто исправлено, добавив:

mongoose.connect('mongodb://myhost/mydatabase');

Где-то рядом с вершиной, прежде чем вы попытаетесь сделать что-нибудь еще. Это не обязательно будет «подключаться» в таком порядке, но методы мангуста сработают. «Асинхронное программирование», читайте дальше.

Также вы не должны зацикливаться, так как вы не ждете «обратного вызова» (это не закрытие, это обратный вызов), чтобы завершить или иным образом «дросселировать» соединение, что может привести к проблемам.

Вместо этого используйте что-то вроде "async". В этом примере .eachLimit() для ограничения количества параллельных операций до разумного уровня:

async.eachLimit(models,10,function(el,callback) {
    Model.create(models[i], function (error, result) {
        // do something maybe but call
        callback(err);   // to signal it is done
    });
},function(err) {
    // comes here on completion or error
});

Помните, что «асинхронный» код должен выполняться на «обратных вызовах» или «обещаниях», чтобы сигнализировать, когда что-то сделано. Unline в «синхронном» программировании, где каждая следующая строка выполняется только после завершения предыдущих строк кода.

В противном случае ваш цикл «for» просто «отправляет все» на сервер и не ждет завершения, прежде чем продолжить выполнение.

Но главной проблемой здесь была связь. Но вы все равно должны исправить остальное, как показано на рисунке.

person Blakes Seven    schedule 11.07.2015
comment
О, вы правы, я подключался к mongodb в своем файле app.js, но этот скрипт не имеет ничего общего с файлом app.js. Кажется, сейчас работает. Вы правы, я имел в виду обратные вызовы, извините, я всегда путаю оба слова! Я знаю, что я не создаю документы синхронно, но в этом случае я не возражаю, кажется, что все работает нормально. Большое спасибо! - person miquelarranz; 11.07.2015
comment
@miquelarranz Да. Подключение в app.js или другом коде основного модуля является стандартом для долго работающих приложений. Но, конечно, этот скрипт автономный, поэтому вам нужно сделать это там. Другой совет здесь — это то, чему вам действительно нужно следовать, чтобы не столкнуться с проблемами в будущем. - person Blakes Seven; 11.07.2015
comment
Да, я ценю совет :) Тестирую знаю скрипт и кажется, что setTimeout не работает, скрипт постоянно добавляет новые документы. Может, это как-то связано с тем, что все работает асинхронно? Есть идеи? - person miquelarranz; 11.07.2015
comment
Неважно, я решил это, неправильно использовал функцию eachLimit. Большое спасибо за твою помощь. - person miquelarranz; 11.07.2015
comment
@miquelarranz Если у вас есть еще вопросы, пожалуйста, задавайте новые вопросы здесь, я уверен, что кто-то ответит на них. Я уже давал вам здесь совет, что ваши вставки должны дождаться завершения, прежде чем остальная часть вашего скрипта продолжится. Единственный намек, который я здесь дам, заключается в том, что это, скорее всего, работа для обработки в стиле cron, а не то, что вы сейчас пытаетесь сделать. - person Blakes Seven; 11.07.2015