2015-07-02 3 views
1

Так что я следующий код в приложение Экспресс для апи POST:Mongoose не сохранять все документы в цикле

var dashSchema = new mongoose.Schema({ 
    key: 'string', 
    status: 'string', 
    assignee: 'string', 
    summary: 'string' 
}); 

var dashData = mongoose.model('dashData', dashSchema); 


app.post('/api/data', function(req, res) { 
    var issues = req.body.issues; 

    for (var i=0;i<issues.length;i++) { 
    dashData.create({key: issues[i].key, status: issues[i].fields.status.name, assignee: issues[i].fields.assignee, summary: issues[i].fields.summary}); 
    } 

    res.end(); 
    }); 

Всякий раз, когда я отправляю массив 5 «вопросов» только первые две записываются в MongoDB. Я предполагаю, что это потому, что это все, что он может написать за время, необходимое для повторения цикла, но я не знаю, как заставить его записывать все данные, а затем возвращать ответ.

Любые идеи?

ответ

1

Самый простой способ будет завершить ответ, когда последняя итерация достигнута:

for (var i=0;i<issues.length;i++) { 
    dashData.create({key: issues[i].key, status: issues[i].fields.status.name, assignee: issues[i].fields.assignee, summary: issues[i].fields.summary}); 
    if(i === issues.length - 1) return res.end(); 
    } 

В качестве альтернативы, вы можете использовать async модуль для большей функциональности, особенно если вам нужно ждать всех запросов к полный.

Update

Как Gabriel справедливо указывал, приведенный выше код не гарантирует, что запросы завершит выполнение до того, как ответ посылают. Я думаю, что я упомянул, что вы должны использовать async especially if you need to wait for all the queries to complete. Во всяком случае, если вы хотите идти без накладных расходов на асинхронном или Promises в любом случае, вы можете сделать что-то вроде:

var ctr = 0; 
    issues.forEach(function(issue){ 
     dashData.create({key: issue.key, status: issue.fields.status.name, assignee: issue.fields.assignee, summary: issue.fields.summary}, function(err, doc){ 
      if (err) { return errorHandler(err); } 
      ctr++; 
      if (ctr === issues.length) return res.end(); 
     }); 
    }); 
+0

Просто потому, что последний 'create' побежал не означает, что все предыдущие' create's сохранены. Они асинхронны. Вам нужно проверить, что все из них выполнены, используя какой-то асинхронный инструмент (async.js, обещания). –

+0

Я знаю, сэр. OP все равно не обрабатывал никаких результатов запроса, просто инициировал их. По крайней мере, в этом контексте он явно обеспокоен выполнением, а не ошибками. Что касается контекста его запроса, мое решение достаточно. Но, чтобы угодить твоим добрым глазам, я уточню свой ответ. – galactocalypse

+0

Хорошее сырое решение для асинхронного использования. –

3

В Mongoose, .create возвращает обещание. Установите библиотеку обещание как bluebird дать вам доступ к Promise.all и вы можете сделать это:

var Promise = require('bluebird'); // could also be Q or another A+ library 

app.post('/api/data', function(req, res, next) { 
    var issues = req.body.issues; 

    // map the issues to an array of promises for created dashData docs 
    var createdPromises = issues.map(function(issue){ 
    return dashData.create({key: issue.key, status: issue.fields.status.name, assignee: issue.fields.assignee, summary: issue.fields.summary}); // returns a promise 
    }); 

    Promise.all(createdPromises).then(function(results){ 
    res.json(results); // only sends when all docs have been created 
    }).then(null, next); // error handler - pass to `next` 

}); 
+0

BTW. Начиная с публикации этого издания в 2015 году, обычная поддержка 'Promise.all' через код ES2015 стала широко распространенной, поэтому вы часто не устанавливаете библиотеку обещаний (в зависимости от вашей среды, поддерживаемых платформ и т. Д.). –

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