tutorial node funciones español actualizar node.js mongodb mongoose

node.js - node - mongoose npm



Hacer que las consultas de mongoose.js se ejecuten sincrónicamente (6)

Tengo dos colecciones de mangostas. El primero almacena una lista de lugares, el segundo es visitas a los lugares. Mi código de nodo se procesa e intenta obtener la lista de visitas a cada lugar y crear una cadena que publico como JSON. La primera consulta se completa antes de que comience el segundo - ¿hay alguna manera de hacer que se ejecuten sincrónicamente?


Aquí hay un método alternativo para hacer solicitudes pseudo sincrónicas usando MongooseJS. La idea aquí es crear una cola de consultas que deben ejecutarse. A continuación, cree una función que se llame de forma recursiva hasta que se agote la cola. Una vez que se agota la cola, la recursión se detiene y se envía una respuesta para la solicitud original. Estoy usando Express Routes, así que todo este código está encapsulado en mi controlador de ruta. En este caso, un HTTP POST.

var express = require(''express''); var router = express.Router(); //POST /auth/create router.post(''/create'', function(req, res) { var queue = [ {"schema": require(''..//models//people.js''), "query": {username: req.body.username}}, {"schema": require(''..//models//members.js''), "query": {username: req.body.username}} ], retData = []; var curTask = 0. function recurse() { if(curTask < queue.length){ var task = queue[curTask]; task.schema.findOne(task.query, function(err, data){ retData.push(err || data); curTask++; recurse(); }) }else{ res.json(retData); } } recurse(); }); module.exports = router;


En estos días, la mangosta es compatible con las promesas, por lo que puede .then() sus consultas. Por ejemplo:

app.get(function (req, res, next) { Users.findOne({ username: req.body.username, password: req.body.password, }).then(user => { if (!user) { res.json({success: false, message: "Username or password incorrect."}); return; } return Notifications.find({ user: user._id }).then(notifications => { res.json({success: true, notifications}); }); ).catch(error => { //console.error(error); //res.json({success: false, error: error.message}); next(error); }); });


No hay una API nativa síncrona para las consultas de mongodb / mangosta (y no querría ninguna en practicidad). Como WiredPrarie menciona, debe encadenar las consultas, y la segunda comienza después de la primera y ejecuta una devolución de llamada. Aquí hay un ejemplo:

function findVisits(placesQuery,callback){ Places.find(placesQuery).exec(function(err,places){ if (err || !places.length){ console.log(''there was a problem''); callback(err, null); }else{ var visitQuery = ... //however you want to filter places Visits.find(visitQuery).exec(function(err2,visits){ if (err2 || !visits.length){ console.log(''there was a problem''); callback(err2,null); }else{ callback(null, visits) } }); } }); }


Para sincronizar, utilicé es6-promise.

var Promise = require(''es6-promise'').Promise , mongoose = require(''mongoose'') , Schema = mongoose.Schema; // define schemas and models. var placeSchema = new Schema({ name: { type: String }, memo: { type: String } }) , Places = mongoose.model(''place'', placeSchema) , visitSchema = new Schema({ placeName: { type: String }, // foreign key for place. visitor: { type: String }, comment: { type: String } }) , Visits = mongoose.model(''visit'', visitSchema); // query for visits by visitor and place. function findVisitsWithPlace(visitor, place) { return new Promise(function (resolve, reject) { Visits.find({ visitor: visitor, placeName: place.name }, function (error, visits) { if (error) { reject(error); return; } // build a result object you want. // () resolve({ place: place, visits: visits }); }); }); } // functions for node route. module.exports = { // - access to "GET /placevisits/?visitor=Visitor-1". get: function (request, response) { var visitor = request.query.visitor; // - to get the places... Places.find({}, function (error, places) { Promise.all(places.map(function (place) { // - run the child queries with parent object... return findVisitsWithPlace(visitor, place); })).then(function (placeAndVisits) { // - and get result. // placeAndVisits have still contain visits empty. // exclude them. var result = []; placeAndVisits.forEach(function (placeandvisit) { if (placeandvisit.visits.length != 0) { result.push(placeandvisit); } }); response.json(result); }); }); } };

y tengo JSON como siguiendo.

[ { "place": { "_id": "564e58a1dbed862155771d46", "name": "Place-A", "memo": "A memo for Place A." }, "visits": [ { "_id": "564e58cedbed862155771d49", "placeName": "Place-A", "visitor": "Visitor-1", "comment": "A comment for Place A by Visitor-1" }, { "_id": "564e58dcdbed862155771d4a", "placeName": "Place-A", "visitor": "Visitor-1", "comment": "2nd visit. Again comment for Place A by Visitor-1" } ] }, { "place": { "_id": "564e58afdbed862155771d47", "name": "Place-B", "memo": "A memo for Place B." }, "visits": [ { "_id": "564e58ebdbed862155771d4c", "placeName": "Place-B", "visitor": "Visitor-1", "comment": "A comment for Place B by Visitor-1" } ] } ]


Si está utilizando Node 8.x, puede utilizar async / await: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

El operador aguarda pausa la ejecución de la función asíncrona hasta que se resuelva Promesa y devuelve el valor. De esta forma, su código se verá más sincrónico:

const query1 = MyModel.find({ name: /john/i }, null, { skip: 10 }); const result1 = await query1.exec(); const query2 = MyModel.find({ name: /john/i }, null, { skip: 100 }); const result2 = await query2.exec();

Las consultas se ejecutarán en sucesión.


Si está utilizando node.js, debe usar https://github.com/caolan/async

cuando tiene que obtener datos de múltiples colecciones, debe encadenar sus consultas varias veces.

Hará su código complejo y difícil de leer y no modularidad. Use asincrónico para crear modularidad usando mongodb y node.js

Código de ejemplo de mi proyecto:

var async = require(''async''); var createGlobalGroup = function(socket, data) { async.waterfall( [ /** * this function is required to pass data recieved from client * @param {Function} callback To pass data recieved from client */ function(callback) { callback(null, socket, data); }, /** * Step 1: Verify User */ verifyUser, /** * Step 2: Check User Access Rights And Roles */ checkUserAccessRightsAndRoles, /** * Step 3: Create Project */ createNewGlobalGroup], function(err, result) { /** * function to be called when all functions in async array has been called */ console.log(''project created ....'') }); } verifyUser = function(socket, data, callback) { //do your query /** * call next function in series * provide sufficient input to next function */ callback(null, socket, data, { "isValidUser": true, }); } checkUserAccessRightsAndRoles = function(socket, data, asyncObj, callback) { //do your query if(condition) { callback(null, socket, data, { roles: result, "isValidUser": asyncObj.isValidUser, "userId": asyncObj.userId, }); } else { //no call back } } var createNewGlobalGroup = function(socket, data, asyncObj, callback) { //wanna stop then no callback }