2015-11-05 7 views
0

Я использую драйвер MongoJS для запуска запросов на моем сервере Nodejs. У меня есть два запроса, которые я хотел бы запустить по порядку, но асинхронный характер javascript оставляет меня с неожиданными результатами, когда я делаю запрос. Вот что у меня есть:Выполнение синхронных запросов MongoJS в NodeJS

app.post('/teams', isLoggedIn, function (req, res){ 

    db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$pull:{"teams":{"_id":req.body.y}}}, 
    function (err, docs) { 
    console.log(docs); res.json(docs); 
    }); 

    db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$push:{"teams":{"_id":req.body.y,"team":req.body.z, "member":true}}}, 
    function (err, docs) { 
    console.log(docs); res.json(docs); 
    }); 

}); 

мне нужны эти запросы, чтобы запустить в порядке ($pull и ТО $push). Я попытался запустить второй запрос в function(err, docs){...} первого запроса, но даже когда я передаю req или переменные версии req, он возвращается как undefined. Каков наилучший способ заставить эти запросы работать по порядку?

Обновление: вот что я в итоге сделал с помощью async (спасибо за отзыв, удовлетворение) на основе this tutorial. Что-то, о чем я должен был упомянуть, было то, что этот запрос существует в цикле, который я не включил в свой пример выше.

async.parallel([ 
     function(callback) { //This is the first task, and callback is its callback task 
      console.log('first1 '+x+'pulled'); 
      db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$pull:{"teams":{"_id":req.body.y}}}, function(err, docs) { 
      //Now we have saved to the DB, so let's tell async that this task is done 
      res.json(docs); 
      callback(); 
     }); 
     }, 
     function(callback) { //This is the second task, and callback is its callback task 
      console.log('second1 '+x+'pushed'); 
      db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$push:{"teams":{"_id":req.body.y,"team":req.body.z, "member":true}}}, callback); //Since we don't do anything interesting in db.save()'s callback, we might as well just pass in the task callback 
      } 
      ], function(err, docs) { //This is the final callback 
      res.json(docs); 
      console.log('Both a and b are saved now'); 
}); 

Обновление 2: Возможно, я говорил слишком рано. Запросы по-прежнему не завершаются так, как ожидалось, примерно в 5% случаев.

ответ

2

Как вы уже упоминали, NodeJS работает асинхронно.

Чтобы синхронизировать все, вам нужно использовать библиотеку, например, async или использовать promises.

Просто быстрый пример того, как вы могли бы сделать что-то работа с использованием ASync «Auto» (я люблю использовать его как у меня гораздо больше контроля над упрощенным методом «водопада»):

async.auto({ 
    pull: function(callback){ 
     db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$pull:{"teams":{"_id":req.body.y}}},callback); 
    }, 
    push: ['pull', function(callback, results){ 
     db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$push:{"teams":{"_id":req.body.y,"team":req.body.z, "member":true}}},callback); 
    }] 
}, function(err, results) { 
    if(err) { 
     console.log(err); 
    } 
    console.log(results.pull); 
    console.log(results.push); 
}); 

Я не проверял код, не стесняйтесь смотреть все это самостоятельно here.

+1

Это не делает вещи происходят синхронно, это только делает его читать, как синхронизация. – Mathletics

+0

Ну, вы могли бы сказать, что это происходит в синхронизации, так как «push» всегда происходит после «pull»? Насколько пользователь должен знать, все происходит синхронно, все данные async инкапсулируются, и нам не нужно беспокоиться об этом. – Andrius

+0

Не будет ли в этом случае метод [** 'async.parallel()' **] (https://github.com/caolan/async#paralleltasks-callback)? Поскольку состояние docs равно _ «параллельное» - это параллельное выполнение задач ввода-вывода, а не параллельное выполнение кода. Если ваши задачи не используют таймеры или не выполняют никаких операций ввода-вывода, они будут выполняться последовательно. Любой синхронный раздел настройки для каждой задачи будет происходить один за другим. JavaScript остается однопоточным. "_ – chridam

1
var Q = require("q"); 

app.post('/teams', isLoggedIn, function (req, res){ 

firstFunction(req,res).then(function(result){ 
    var resultFromFirst = result 
    db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$push:  {"teams":{"_id":req.body.y,"team":req.body.z, "member":true}}}, 
     function (err, docs) { 
      console.log(docs); res.json(docs); 
     }); 

}) 


}); 

var firstFunction = function (req,res) { 
console.log("first function") 
var d1 = Q.defer(); 
    db.collection.update({"_id":mongojs.ObjectId(req.body.x)},{$pull: {"teams":{"_id":req.body.y}}}, 
    function (err, docs) { 
     console.log(docs); res.json(docs); 
     d1.resolve(docs); 
    }); 


return d1.promise; 
} 

Перед Run:

npm install q -g 

использовать Суды, если какие-либо проблемы при установке пакета

+0

Что делать, если я запускаю свои два запроса в цикле 'for'? Исходный '$ pull' отлично работает, но когда я перехожу к' $ push', итератор, определенный моим циклом, не определен. – mjoyce91

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