【问题标题】:Docpad: using extendTemplateData via mongoose callbackDocpad:通过猫鼬回调使用extendTemplateData
【发布时间】:2014-03-13 09:08:04
【问题描述】:

我正在尝试构建一个简单的插件来从 Mongo 获取数据到一个对象中,我可以在渲染时对其进行迭代。完整的代码在我的project 中,但它的本质是模拟馈线示例的失败尝试。我知道猫鼬的东西在控制台日志工作时工作,但是将内容发送到 docpad 对象让我失望

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()

使用 node-inspector 并通过编辑 docpad.coffee 触发重新生成,我可以看到 opts 有一个字段 templateData,但它是空的,并且与 docpad.templateData 非常不同,所以我在插件。我可以看到其他人在 { } 中放了一个名字,但我不知道这是做什么的。

完成插件代码后,我看到我的数据库数据成为了一个承诺的参数,所以也许这就是它应该与 docpad.config.templateData 重新集成的地方,但实际上这似乎不会发生

【问题讨论】:

    标签: mongodb mongoose docpad


    【解决方案1】:

    所以这里的主要问题是我们有一个异步函数getGetsData 在同步函数内部执行,您的模板引擎。这很简单,是不可能的,因为模板引擎会继续做它的事情,而同步的事情发生在后台。这只是一般只编写 node.js/asynchronous 代码的问题。

    解决这个问题很容易。

    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 中定义的完成回调(next)。我们将要做的是,我们将在有return gigs 的地方调用下一个,所以让我们更改@ 987654343@转return 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
            @
    

    【讨论】:

    • 太棒了。代码需要最后一个 next() 才能运行。
    猜你喜欢
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2015-10-08
    • 1970-01-01
    相关资源
    最近更新 更多