sincronas promesas node funciones entre diferencia await async asincrono asincronas anidadas asynchronous node.js mongoose

asynchronous - promesas - ¿Cómo trabajar con código asíncrono en las propiedades virtuales de Mongoose?



promesas en angular 6 (4)

Estoy tratando de trabajar asociando documentos en diferentes colecciones (no documentos incrustados) y si bien hay un problema para eso en Mongooose, estoy tratando de solucionarlo ahora cargando el documento asociado con una propiedad virtual como se documenta en El sitio web de Mongoose .

El problema es que el getter para un virtual toma una función como argumento y usa el valor de retorno para la propiedad virtual. Esto es genial cuando lo virtual no requiere ninguna llamada asíncrona para calcular su valor, pero no funciona cuando necesito hacer una llamada asíncrona para cargar el otro documento. Aquí está el código de ejemplo con el que estoy trabajando:

TransactionSchema.virtual(''notebook'') .get( function() { // <-- the return value of this function is used as the property value Notebook.findById(this.notebookId, function(err, notebook) { return notebook; // I can''t use this value, since the outer function returns before we get to this code }) // undefined is returned here as the properties value });

Esto no funciona ya que la función vuelve antes de que finalice la llamada asíncrona. ¿Hay alguna forma en que pueda usar una biblioteca de control de flujo para hacer que esto funcione, o puedo modificar la primera función para pasar la llamada findById al receptor en lugar de una función anónima?



El enfoque de Josh funciona muy bien para búsquedas de documentos individuales, pero mi situación era un poco más compleja. Necesitaba hacer una búsqueda en una propiedad anidada para una matriz completa de objetos. Por ejemplo, mi modelo se parecía más a esto:

var TransactionSchema = new Schema({ ... , notebooks: {type: [Notebook]} }); var NotebookSchema = new Schema({ ... , authorName: String // this should not necessarily persist to db because it may get stale , authorId: String }); var AuthorSchema = new Schema({ firstName: String , lastName: String });

Luego, en mi código de solicitud (estoy usando Express), cuando obtengo una Transacción, quiero que todos los cuadernos con el apellido del autor:

... TransactionSchema.findById(someTransactionId, function(err, trans) { ... if (trans) { var authorIds = trans.notebooks.map(function(tx) { return notebook.authorId; }); Author.find({_id: {$in: authorIds}, [], function(err2, authors) { for (var a in authors) { for (var n in trans.notebooks { if (authors[a].id == trans.notebooks[n].authorId) { trans.notebooks[n].authorLastName = authors[a].lastName; break; } } } ... });

Esto parece tremendamente ineficiente y intrépido, pero no pude encontrar otra manera de lograrlo. Por último, soy nuevo en node.js, mongoose y , así que perdóneme si este no es el lugar más apropiado para ampliar esta discusión. Es solo que la solución de Josh fue la más útil en mi eventual "solución".


Puede definir un método virtual, para el que puede definir una devolución de llamada.

Usando tu ejemplo:

TransactionSchema.method(''getNotebook'', function(cb) { Notebook.findById(this.notebookId, function(err, notebook) { cb(notebook); }) });

Y si bien el único comentarista parece ser uno de esos tipos pedantes, tampoco debes tener miedo de incrustar documentos. Es uno de los puntos fuertes de mongos por lo que entiendo.

Uno usa el código anterior como tal:

instance.getNotebook(function(nootebook){ // hey man, I have my notebook and stuff });


Si bien esto aborda el problema más amplio en lugar de la pregunta específica, aún pensé que valía la pena enviarlo:

Puede cargar fácilmente un documento asociado de otra colección (con un resultado casi idéntico al definir un virtual) mediante el uso de la función de rellenado de consultas de Mongoose. Usando el ejemplo anterior, esto requiere especificar la referencia del ObjectID en el esquema de Transaction (para apuntar a la colección de Notebook), luego llamar a populate(NotebookId) al construir la consulta. La documentación de Mongoose vinculada aborda esto bastante a fondo.

No estoy familiarizado con la historia de Mongoose, pero supongo que la populate no existía cuando se presentaron estas respuestas anteriores.