2014-02-14 81 views
0

我試圖構建一個簡單的插件,以便從Mongo獲取數據到一個可以在呈現時迭代的對象。完整的代碼在我的project中,但其實質是嘗試模仿feedr示例失敗。我知道貓鼬的東西是工作作爲控制檯日誌的作品,但得到發送到docpad對象的內容被擊敗我Docpad:通過貓鼬回調使用extendTemplateData

class mongoPlugin extends BasePlugin 
    name: 'mongo' 

    # Fetch list of Gigs 
    getGigsData: (opts) -> 
     mongoose.connect ('mongodb://localhost/test') 
     db = mongoose.connection; 
     db.on 'error', console.error.bind(console, 'connection error:') 
     db.once 'open',() -> 
      gigsSchema = mongoose.Schema { 
       date : String, 
       location : String 
      } 

      Gigs = mongoose.model 'Gigs', gigsSchema 

      Gigs.find {}, (err, gigs) -> 
       mongoose.connection.close() 
       if err then console.error "db error" 
       else 
        console.dir gigs 
        opts["getGigsData"] = gigs 
        opts.templateData["getGigsData"] = gigs 
        return gigs 

    extendTemplateData: (opts) -> 
     opts.templateData["getGigsData"] = @getGigsData() 

使用節點檢查和編輯docpad.coffee觸發再生,我可以看到, opts有一個字段templateData,但它是空的,並且與docpad.templateData非常不同,所以我在插件中拾取了錯誤的對象。我可以看到其他人做了一個在{}中放置一個名字的伎倆,但我不知道它會做什麼。

完成插件代碼我看到我的數據庫中的數據變爲參數傳遞給一個承諾,所以也許這就是它應該與docpad.config.templateData重新整合,但似乎並沒有在實踐中

發生後

回答

0

所以這裏的主要問題是我們有一個異步函數getGetsData在一個同步函數,你的模板引擎中執行。簡而言之,這是不可能的,因爲模板引擎會繼續執行它的功能,而同步事件發生在後臺。這只是編寫node.js /異步代碼的一個問題。

修復這個很容易。

  1. opts.templateData["getGigsData"] = @getGigsData()電話getGigsData沒有越過opts,這樣當getGigsData嘗試並使用OPTS,它不能,這樣就會拋出一個錯誤。造成這種情況的解決方法是做@getGigsData(opts)

  2. opts.templateData["getGigsData"] = @getGigsData(opts)分配的@getGigsData(opts)的模板數據的返回值,但是,這樣做的結果是db.once調用的結果,因爲這是將在該範圍內退還。當您執行return gigs時,實際上這是Gigs.find調用中(err, gigs) ->回調的返回值,而不是getGigsData的返回值。這都是關於示波器的。

  3. 由於數據庫的東西是異步的,我們需要使getGigsData異步。要做到這一點,我們改變extendTemplateData: (opts) ->extendTemplateData: (opts,next) ->使其同步,並改變opts.templateData["getGigsData"] = @getGigsData()簡單return @getGigsData(opts,next)

  4. 現在我們有事件並調用異步的。我們現在需要使getGigsData的定義支持它。因此,讓改變getGigsData: (opts) ->getGigsData: (opts,next) ->採取在完成回調,我們在步驟3中定義我們所要做的,就是我們接下來請我們在那裏有return gigsnext),所以讓我們改變return gigsreturn next()

  5. 它應該現在工作。但是作爲一點清理,我們可以通過將if err then console.error "db error"更改爲return next(err) if err來使錯誤處理更好。您需要修正縮進,因爲我們需要刪除else塊。

考慮所有這些,並施加更多的清潔,你會這樣結束了:

class mongoPlugin extends BasePlugin 
    name: 'mongo' 

    config: 
     hostname: 'mongodb://localhost/test' 

    # Fetch list of Gigs 
    getGigsData: (opts={}, next) -> 
     config = @getConfig() 
     docpad = @docpad 

     mongoose.connect(config.hostname) 
     db = mongoose.connection 
     db.on 'error', (err) -> 
      docpad.error(err) # you may want to change this to `return next(err)` 

     db.once 'open', -> 
      gigsSchema = mongoose.Schema { 
       date: String, 
       location: String 
      } 

      Gigs = mongoose.model('Gigs', gigsSchema) 

      Gigs.find {}, (err, gigs) -> 
       mongoose.connection.close() 
       return next(err) if err 
       return next(null, gigs) 

     # Chain 
     @ 

    extendTemplateData: (opts,next) -> 
     @getGigsData null, (err, gigs) -> 
      return next(err) if err 
      opts.templateData.gigs = gigs 

     # Chain 
     @ 
+0

那太好了。代碼需要一個final()來運行。 –