2014-11-23 278 views
4

我正在尋找關於如何鏈接使用mongodb/mongoose「查找或創建」功能的承諾的建議。貓鼬 - 鏈接承諾

我已經試過目前:

userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { 
    var self = this; 
    return this.findOne({facebookId: facebookId }).exec() 
    .then(function (user) { 
     if (!user) { 
     return self.model.create({ facebookId: facebookId, name: name, email: email }).exec().then(function (user) { 
      return user; 
     }); 
     } 
     return user; 
    }); 
}; 

而且我把它從我的(節點/快遞)API端點:

User.model.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email).then(function (user) { 
    return res.sendStatus(200).send(createTokenForUser(user)); 
    }, function (err) { 
    return res.sendStatus(500).send({ error: err }); 
    }); 

的問題是,雖然:

  1. 即使用戶從findOne查詢中爲null,創建永遠不會被調用
  2. 我是n OT確保我使用的是正確的諾言風格/最有效的編碼風格
  3. 我是否正確如處理錯誤只在頂層或者我需要在各個層面做

誰能明白我做錯了,我怎麼能做得更好?

謝謝。

UPDATE

問題的原因是,

self.model.create(...) 

應該是(無參考模型)

self.create(...) 

不過,我現在需要知道我」 m做錯誤處理錯誤 - 我可以看到發生錯誤,但我看不到原因。

我仍然有存在的一些錯誤,我知道,因爲我得到的500

return res.sendStatus(500).send({ error: err }); 

狀態,但實際的錯誤信息/細節是空的。

+0

1.嘗試'return self.model.create(...' 2.鏈接承諾時,總是返回一個新的承諾或最終的值 3.最後有一個單一的錯誤函數就好了 – Ivancho 2014-11-23 22:38:41

+0

謝謝,我原本有這樣的回報,但它沒有幫助,只是拿出來看效果。 – prule 2014-11-23 22:40:55

+0

我已經編輯了這個問題,讓回來的回來。其他想法? – prule 2014-11-23 22:42:47

回答

2

的問題可能是:

  1. 創建方法返回一個承諾和它好好嘗試一下有方法EXEC
  2. 如果你想在你的自定義的方法使用則()你必須返回一個承諾,但你要返回一個貓鼬文檔:返回用戶;

這將始終返回一個承諾,它可以讓你的方法後,使用則()(您必須添加mpromise模塊):

userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { 
    var self = this; 
    var Promise = require('mpromise'); 
    var promise = new Promise; 
    this.findOne({facebookId: facebookId }).exec() 
    .then(function (user) { 
     if(user) { 
      promise.fulfill(user); 
      return; 
     } 

     self.model.create({ facebookId: facebookId, name: name, email: email }) 
      .then(function (user) { 
       promise.fulfill(user); 
       return; 
      }); 
    }); 
    return promise; 
}; 

希望這可以幫助您

+0

這看起來很像[deferred antipattern](http://stackoverflow.com/q/23803743/1048572) – Bergi 2015-03-26 17:36:31

0

您的問題(以及來自@EduardoRodríguez的後續答案)幫助我解決了類似的問題,所以歡呼!但是,使用最新版本的貓鼬+ ES6解構和箭頭的功能,我能得到它下降到一個類似於以下內容:

userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { 
    var User = this; 
    return User.findOne({facebookId}) 
    .then(user => user || User.create({facebookId, name, email})); 
}; 

...然後:

User.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email) 
    .then(user => res.sendStatus(200).send(createTokenForUser(user)) 
    .catch(error => res.sendStatus(500).send({error}); 

注:此不包括通過配置貓鼬使用本地ES6承諾:

mongoose.Promise = global.Promise; 

我仍然很新的這一點,但希望這可以幫助別人前進(我的作品)。