Mongoose: Model.create Promise resolvida, embora nenhum documento tenha sido salvo

Criado em 1 fev. 2018  ·  3Comentários  ·  Fonte: Automattic/mongoose

Olá pessoal,

Estou usando o mongoose versão 5.0.3 e o node versão 9.4.0. De acordo com a documentação do mongoose, model.create deve retornar uma promessa que, presumo, é resolvida à medida que o documento criado é salvo no banco de dados. No entanto, conforme mostrado pelo código abaixo, parece que a promessa é resolvida antes que o documento seja salvo no banco de dados.

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 não encontrou nenhum documento. Além disso, "criado" está aparecendo no final do terminal, portanto, o retorno de chamada do método de criação é executado como se o await não estivesse esperando que a tarefa assíncrona 'criar' fosse concluída.

No entanto, ao adicionar uma promessa que é resolvida assim que o retorno de chamada de create é acionado, conforme mostrado abaixo, obtemos o 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 }

Agora temos o resultado esperado.

Todas as funções que operam no banco de dados retornam uma promessa de que, se resolvida, indica que a operação foi realizada, especificamente Consulta. Suponho que esse também seja o caso de model.create, embora ele não retorne um objeto de consulta estritamente falando. Também me pergunto o que significa a promessa de retorno cumprida, uma vez que não mostra que o documento foi criado no banco de dados. Talvez eu tenha perdido todo o ponto, mas acho um pouco ambíguo

Comentários muito úteis

Acho que me lembro de ter lido na documentação do 4.x que se você passar um retorno de chamada para model.create, ele não retornará uma promessa.

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

se você retirar o callback:

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

a fonte 5.x para model.js confirma isso chamando utils.promiseOrCallback

Todos 3 comentários

Acho que me lembro de ter lido na documentação do 4.x que se você passar um retorno de chamada para model.create, ele não retornará uma promessa.

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

se você retirar o callback:

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

a fonte 5.x para model.js confirma isso chamando utils.promiseOrCallback

Sim, @lineus está correto, posso encerrar esse problema @CodeurSauvage ?

@CodeurSauvage @lineus está correto, o mongoose 5 não retorna uma promessa se um retorno de chamada for especificado. Seu script funcionará se você substituir:

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

Com:

    await model.create({ a: 'test'}).then(result => console.log('created'));
Esta página foi útil?
0 / 5 - 0 avaliações