2013-03-08 2 views
0

Постараюсь быть кратким, насколько это возможно - Mongoose не кажется, чтобы сохранить записи, пока весь скрипт не заканчивается, даже если сохранить() часть называется асинхронно:Почему Mongoose не сохраняет записи по сценарию?

var reallyBigData = require('./data.json'); 

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

this.on('importData', importData); 

for(var i in reallyBigData) { 
    this.emit('importData', reallyBigData[i]); 
}; 

Это грубое упрощение , Но ты получил идею. Когда я запускаю скрипт и запрашиваю Mongo, я не вижу никаких записей по мере запуска скрипта. Если я ограничу число, чтобы сказать, 30, и импортировать те, которые он заканчивает быстро, и я вижу записи позже.

Почему Mongoose не сохраняет каждую запись по мере выполнения скрипта?

ответ

2

Проблема заключается в том, что x.save() (или newObj.save()) является асинхронным, и у вас нет ничего ожидающего завершения его, кроме самого узла.

Будучи асинхронным, только запускает задачу обновления коллекции в MongoDB и выходит сразу после. Это не будет на самом деле «не сделал» до позже, когда дополнительный обратный вызов будет называться:

x.save(function (err, instance) { 
    // at this point, it either erred or saved 
}); 

Хотя, возможно, для x.save() закончить почти мгновенно. Чем меньше количество записей, заканчивающихся вовремя, чтобы увидеть, значит у вас есть условие гонки, которое закончит сначала: запросы к MongoDB или Node/V8, выполняющие блок кода?

И, используя EventEmitter, по крайней мере, как вы его выборку здесь, не достаточно, чтобы сделать ваш асинхронный цикл, так как вы все еще emit ИНГ событий синхронно и emit() цикла будут через любые обработчик синхронно.

Однако существует множество «потока управления» доступных библиотек, которые могут помочь. Они включают в себя реализацию promises, futures и итераторы как async:

var reallyBigData = require('./data.json'); 

async.each(Object.keys(reallyBigData), 
    function (key, callback) { 
     new Obj({ x: reallyBigData[key] }).save(callback); 
    }, 

    function (err, results) { 
     // called with an `err` or an `Array` of `results` (saved `Obj`s) 
    } 
); 
+0

Это интересно, я работал над проблемой, выбрасывая Mongoose и просто используя собственный драйвер. Мне интересно, делает ли Mongoose какое-то кэширование запросов. Я буду экспериментировать с ним больше, но казалось, что Mongoose не обрабатывал * никаких * запросов вставки до тех пор, пока не закончится большая петля. – James

+0

@James Да, Mongoose выполняет очередь запросов, чтобы вы могли * вызывать * их синхронно и запускать их asynchrounously. Это одно возможное решение для «* callback hell *». Кроме того, собственный драйвер по-прежнему является асинхронным, и вы все равно должны использовать обратные вызовы с 'insert()' и асинхронным итератором. –

0

Во-первых, я думаю, что у вас есть неприятную ошибку здесь:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    Obj.x = data.x; 
    x.save(); 
}; 

Который должен, скорее всего, читать как:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

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

+0

Вы правы. Это была опечатка в моем вопросе, а не в коде.Спасибо хоть. – James

Смежные вопросы