Mongoose: Model.create Promise resuelto aunque no se guardó ningún documento

Creado en 1 feb. 2018  ·  3Comentarios  ·  Fuente: Automattic/mongoose

Hola, todos,

Estoy usando la versión 5.0.3 de la mangosta y la versión 9.4.0 del nodo. De acuerdo con la documentación de mangosta model.create debería devolver una promesa que, supongo, se resuelve cuando el documento creado se guarda en la base de datos. Sin embargo, como se muestra en el código a continuación, parece que la promesa se resuelve antes de que el documento se guarde en la base de datos.

async function test(){

    let schema = new mongoose.Schema({a: String});

    let model = mongoose.model('test', schema);

    await model.remove({}).exec();

    await model.create({ a: 'test'}, 
       (err,result)=> {console.log('created');});

    await model.findOneAndUpdate(
        { a : 'test' } , 
        { a: 'newValue'}
    )
    .exec((err, result) => {
        console.log('update : '+result);
    });

    await model.find({a: 'test'},(err,result) => {
        console.log(result); 
    });

}

output in terminal : 
    update : null
    found :
    created

findOneAndUpdate no encuentra ningún documento. Además de que "creado" aparece al final en la terminal, por lo tanto, la devolución de llamada del método de creación se ejecuta como si la espera no estuviera esperando a que se realizara la tarea asíncrona "crear".

Sin embargo, al agregar una promesa que se resuelve una vez que se activa la devolución de llamada de create, como se muestra a continuación, obtenemos el resultado esperado:

async function test(){

    let schema = new mongoose.Schema({a: String});

    let model = mongoose.model('test', schema);

    await model.remove({}).exec();

    await new Promise((resolve,reject) => {
        model.create({ a: 'test'}, 
       (err,result)=> {
            console.log('created');
            resolve();
        });
    });

    await model.findOneAndUpdate(
        { a : 'test' } , 
        { a: 'newValue'}
    )
    .exec((err, result) => {
        console.log('update : '+result);
    });

    await model.find({a: 'newValue'},(err,result) => {
        console.log('found : ' +result); 
    });

}

output in terminal: 
     created
     update : { _id: 5a735fbc1fe826233014d62d, a: 'test', __v: 0 }
     found : { _id: 5a735fbc1fe826233014d62d, a: 'newValue', __v: 0 }

Ahora tenemos el resultado esperado.

Todas las funciones que operan en la base de datos devuelven una promesa que, si se resuelve, indica que la operación se ha realizado, específicamente Consulta. Supongo que ese también fue el caso de model.create aunque no devuelve un objeto de consulta estrictamente hablando. También me pregunto qué significa la promesa devuelta cumplida, ya que no muestra que el documento se haya creado en la base de datos. Quizás me perdí todo el punto, pero lo encuentro un poco ambiguo.

Comentario más útil

Creo recordar haber leído en los documentos 4.x que si pasa una devolución de llamada a model.create, no devuelve una promesa.

let x = model.create({ a: 'test' }, () => {})
  x.then(console.log(x)) //TypeError: Cannot read property 'then' of undefined

si saca la devolución de llamada:

let x = model.create({ a: 'test' })
  x.then(console.log(x)) // Promise { <pending> }

la fuente 5.x para model.js lo confirma llamando a utils.promiseOrCallback

Todos 3 comentarios

Creo recordar haber leído en los documentos 4.x que si pasa una devolución de llamada a model.create, no devuelve una promesa.

let x = model.create({ a: 'test' }, () => {})
  x.then(console.log(x)) //TypeError: Cannot read property 'then' of undefined

si saca la devolución de llamada:

let x = model.create({ a: 'test' })
  x.then(console.log(x)) // Promise { <pending> }

la fuente 5.x para model.js lo confirma llamando a utils.promiseOrCallback

Sí, @lineus es correcto, ¿puedo cerrar este problema @CodeurSauvage ?

@CodeurSauvage @lineus es correcto, mongoose 5 no devuelve una promesa si se especifica una devolución de llamada. Su secuencia de comandos funciona si reemplaza:

    await model.create({ a: 'test'}, 
       (err,result)=> {console.log('created');});

Con:

    await model.create({ a: 'test'}).then(result => console.log('created'));
¿Fue útil esta página
0 / 5 - 0 calificaciones