Mongoose: Adicione o valor de retorno 'promessa' à operação de salvamento do modelo

Criado em 16 abr. 2013  ·  50Comentários  ·  Fonte: Automattic/mongoose

Adicionar suporte de retorno de promessa para salvar a operação, atualmente retorna indefinido. Existem vários caminhos de retorno, dependendo da validação e do estado de salvamento, que precisariam ser atualizados. Isso permitiria o encadeamento de várias operações de salvamento com .then() em vez de aninhamento.

enhancement

Comentários muito úteis

Por enquanto estou fazendo assim:

userSchema.methods.saveAsync = function() {
  return new Promise((resolve,reject) => {
    this.save((err) => {
      if(err) return reject(err)
      resolve()
    })
  })
}

Todos 50 comentários

Estou adicionando isso à lista para 4.x. Relaciona-se a como o middleware é implementado (hooks.js).

Maravilha, obrigado. Eu implementei uma versão do .when do jquery como uma extensão do objeto Promise do mangusto para o meu projeto. Isso é algo que você estaria interessado em ter um pull request?

var p1 = Users.find();
var p2 = Animais.find();
Promise.when(p1, p2).addBack(function(err, users, animals) {
//etc
});

Não, obrigado. Eu realmente não quero adicionar mais recursos que possam ser implementados fora do mangusto. Já está inchado.

Para outros que encontrarem este tópico, aqui está: https://github.com/wshaver/mongoosewhen

@wshaver publique isso no npm e adicione uma tag mangusto para que apareça em http://plugins.mongoosejs.com

Movido para aqui para estar em conformidade com o uso de traços de outros plugins Mongoose no nome: https://github.com/wshaver/mongoose-when

Publicado no npm, marcado. Ainda não apareceu, mas talvez haja um atraso.

@wshaver legal. ele atualiza uma vez por dia.

Depois de cavar no #1446, acho que posso conseguir isso sem remover "hooks.js".
Luz verde?

Vá em frente

Na segunda-feira, 7 de outubro de 2013, Refael Ackermann escreveu:

Depois de cavar #1446 https://github.com/LearnBoost/mongoose/issues/1446Acho que posso conseguir isso sem remover "hooks.js".
Luz verde?


Responda a este e-mail diretamente ou visualize-o no Gi tHubhttps://github.com/LearnBoost/mongoose/issues/1431#issuecomment -25792310
.

Arão
@aaronheckmann https://twitter.com/#!/aaronheckmann
soundcloud.com/ajhecky
github.com/aheckmann

Grande PR pronto

Isso realmente me ajudaria também. Deve ser possível chamar myDoc.save().exec() - então basicamente save deve retornar uma consulta que pode ser executada. Ou qual o motivo, que Save não retorna uma Query?

+1 para retorno de promessa se omitirmos o retorno de chamada

A correção está na ramificação master , planejada para ser incluída na versão 3.10.

Isso inclui uma promessa retornada para a operação de criação de modelo?

@GDownes create() já retorna uma promessa :) http://mongoosejs.com/docs/api.html#model_Model.create

alguma data de lançamento planejada para 3.10? :)

@swayf 4.0 ainda falta alguns meses. Minha linha na areia é 2 de setembro, mas espero que antes disso :)

Isso ainda está programado para uma próxima versão?

Sim, isso será em 4.0, porém, ainda não tem uma data de lançamento para isso. A última estimativa não estava certa :(

:+1:

+1 porque:

Eu preciso salvar 2 documentos em um teste de mocha antes do gancho, e essa funcionalidade me permitiria executar o retorno de chamada done() assim que os dois modelos forem salvos.

Tentei usar o método Collection.insert([docs], done) , mas não aciona a lógica Schema.pre('save') que preciso fazer hash de alguns valores.

@arathael você sempre pode usar o módulo assíncrono para salvar seus dois documentos em async.parallel e executar feito no callback

Obrigado cara, na verdade estou testando isso agora. Eu apenas entrei porque acho que o suporte nativo do ODM seria ótimo.

+1

Eu uso o ES7 experimental await/async usando 6to5. Se record.save() retornou uma promessa, posso fazer isso:

try {
  await record.save()
} catch(err) {
  ...
}

Por enquanto estou fazendo assim:

userSchema.methods.saveAsync = function() {
  return new Promise((resolve,reject) => {
    this.save((err) => {
      if(err) return reject(err)
      resolve()
    })
  })
}

+1 para @aaronshaf , funciona muito bem para mim, eu escreveria também em ES5 para quem não está usando ES6. Obrigado

Aqui está o que eu fiz por enquanto. Obviamente, Q não é necessário, mas é o que uso para promessas em outros lugares.

/*
 * Hack until mongoose 3.10 comes out. See this: https://github.com/LearnBoost/mongoose/issues/1431
 */
mongoose.Document.prototype.savePromise = function () {
    var that = this;
    return Q.Promise(function(resolve, reject) {
        that.save(function (err, item, numberAffected) {
            if (err) {
                reject(err);
            }
            resolve(item, numberAffected);
        });
    });
};

mongoose.Document.prototype.removePromise = function () {
    var that = this;
    return Q.Promise(function(resolve, reject) {
        that.remove(function (err, item) {
            if (err) {
                reject(err);
            }
            resolve(item);
        });
    });
};

+1 no hack @jhullfly , no entanto, acho que a resolução de Q leva apenas um argumento, então numberAffected é descartado, precisa colocá-los em uma matriz ou algo assim para obter acesso a ambos:

mongoose.Document.prototype.savePromise = function () {
    var that = this;
    return Q.Promise(function(resolve, reject) {
        that.save(function (err, item, numberAffected) {
            if (err) {
                reject(err);
            }
            resolve([item, numberAffected]);
        });
    });
};

1+ por promessa sendo devolvida do save!

Agora save retorna a promessa em 4.0.1. Felicidades.

+1

@arathael +1

Existe documentação relacionada a como save é usado com Promises?

Tentei o seguinte e não funcionou:

var User = mongoose.model('User');
var u = new User();
u.save().then(function() {
// never gets here.
});
// I even tried the following, and neither works.
u.save().then(function() {}).end();

Você está no mongoose 4.0.1 e instalou o npm?

@Ouwen Sim, estou executando o 4.0.1 e sim, eu fiz ou então eu teria recebido um erro se o mangusto não estivesse instalado.

O problema é que then parece nunca ser chamado. Tenho certeza de que estou fazendo algo estranho (ou então haveria bugs arquivados rapidamente), mas não consigo raciocinar o que, é isso que estou curioso para ver se há algum exemplo/documentação sobre isso.

Hum, muito estranho. Eu sei que estava executando o 3.8.8 e esqueci de npm install para 4.0.1 e é por isso que uma promessa não foi retornada de u.save()

O que você escreveu deve funcionar.

@limianwang você está se conectando com sucesso a um servidor mongodb? Você pode me fornecer um exemplo independente que reproduza isso?

Parece que o objeto de promessa retornado por .save() não é o mesmo que outras promessas, ele tem catch/caught em vez de onReject.

mangusto 4.1.10 e ...

var u = new User();
u.save().then(...)

ainda não retorna uma promessa

@xrado forneça um exemplo mais substancial. Temos testes para mostrar que deve funcionar no mangusto 4.1.10.

@vkarpov15 meu mal, eu tentei novamente e funciona .. eu não sei o que eu estava fazendo antes .. desculpe

Eu tenho o mesmo problema, Save salva os dados no db imediatamente e não chama o código no then. O estranho é que eu tinha outro pedaço de código que chamava o bloco then e a promessa funcionava.

Código (a parte user.save() o salva, então não é definido, mas nunca chamado)

user.save().then( function(userX) { // salvar funciona
console.log(2); // isso não é chamado
}).end() // não chamado
.then(undefined, function(err){
console.log('err:' + err ); // não chamado
});

Atualização eu usei a maneira antiga e funciona assim:

user.save(função (erro, novo usuário) {
if (err) console.log('err=' + err);
console.log('usuário salvo');
});

WTF: A solução foi simplesmente mudar a versão do mangusto para ^4.1.9 de "3.8.X"

Then user.save().then( function(userX) { // salvar funciona
console.log(2);
}).fim()
.then(undefined, function(err){
console.log('err:' + err );
});

FUNCIONA!!!!!!!!!!! doce....

@nickjohngray que bom que você descobriu :) Eu recomendo fortemente que você leia o guia de promessas nos documentos antes de continuar a usar promessas com mangusto - não se preocupe, é uma leitura curta.

Estou tendo o mesmo problema... Eu realmente espero não ter que fazer o downgrade de uma versão principal inteira apenas para fazer um save funcionar dentro de uma promessa.

@jhyland87 forneça exemplos de código para que eu possa ver qual é o problema.

@vkarpov15 eu fiz, no ticket

Isso foi corrigido no outro ticket...

Basicamente, este código:

var User = mongoose.model('User');
var u = new User();
u.save().then(function() {
// never gets here.
});

Só precisava de um return adicionado ao salvar um documento .. então:

var User = mongoose.model('User');
var u = new User();
return u.save().then(function() {
// never gets here.
});

@jhyland87 , FYI - outro exemplo de encadeamento de promessas com o Mongoose .

Isso ainda é um problema?

Eu tenho o seguinte código (usando TypeScript) ...

User.findById(id)
.exec()
.then((user) => {
  user.name = 'new name from wherever!';
  return user.save();
})
.then((user) => {
  // want to do more stuff with the user object once it has been saved successfully...
  // ... but it never makes it here!!!
};

No entanto, quando adiciono um retorno de chamada vazio à função save() , tudo parece bem, como abaixo ...

User.findById(id)
.exec()
.then((user) => {
  user.name = 'new name from wherever!';
  return user.save(() => {
    // unwanted empty callback... hmmm?
  });
})
.then((user) => {
  // we made it here!!! but now...
  // user === undefined :(
};

Você está usando o mpromise? Tente mudar para mongoose.Promise = global.Promise;

Esta página foi útil?
0 / 5 - 0 avaliações