Docpad:通过猫鼬回调使用extendTemplateData [英] Docpad: using extendTemplateData via mongoose callback

查看:58
本文介绍了Docpad:通过猫鼬回调使用extendTemplateData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to build a simple plugin to get get data from Mongo into an object over which I can iterate when rendering. The full code is in my project, but the essence of it is a failed attempt to emulate the feedr example. I know the mongoose stuff is working as the console log works, but getting the content sent to the docpad object is defeating me

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有很大的不同,因此我在其中选择了错误的对象插件.我可以看到其他人在{}中放置了一个名称的技巧,但是我不知道这样做是什么.

Using node-inspector and triggering a regeneration by editing docpad.coffee, I can see that opts has a field templateData, but it is empty, and is very different from docpad.templateData, so I am picking up the wrong object in the plugin. I can see others did a trick of placing a name in { } but I don't know what that does.

在完成插件代码之后,我看到我的数据库数据成为了Promise的参数,所以也许应该将它与docpad.config.templateData重新集成在一起,但实际上并不会发生这种情况

After completing the plugin code I see that my database data becomes the argument to a promise, so perhaps that's where it is supposed to be reintegrated with the docpad.config.templateData but that does not seem to happen in practise

推荐答案

所以这里的主要问题是,我们有一个异步函数getGetsData在模板引擎即同步函数中执行.这是不可能的,因为模板引擎将继续执行其任务,而同步任务则在后台发生.一般来说,这只是编写node.js/异步代码的问题.

So the main issue here is that we have an asynchronous function getGetsData being executed inside a synchronous function, your templating engine. This simply, isn't possible, as the templating engine will go on and do its thing, while the synchronous stuff happens in the background. This is just an issue with just writing node.js/asynchronous code in general.

解决此问题的方法很容易.

The fixes for this is pretty easy to do.

  1. opts.templateData["getGigsData"] = @getGigsData()调用getGigsData而不会越过opts,因此,当getGigsData尝试并使用opts时,它不会,因此会引发错误.解决此问题的方法是@getGigsData(opts)

  1. opts.templateData["getGigsData"] = @getGigsData() calls getGigsData without passing over the opts, so that when getGigsData tries and uses the opts, it can't, so that would throw an error. The fix for this is to do @getGigsData(opts)

opts.templateData["getGigsData"] = @getGigsData(opts)@getGigsData(opts)的返回值分配给模板数据,但是,其结果是db.once调用的结果,因为这将在该范围中返回.当您执行return gigs时,实际上是Gigs.find调用中(err, gigs) ->回调的返回值,而不是getGigsData的返回值.都是关于范围的.

opts.templateData["getGigsData"] = @getGigsData(opts) assigns the return value of @getGigsData(opts) to the template data, however, the result of this is the result of the db.once call, as that is what will be returned in that scope. When you do return gigs, that's actually the return value for the (err, gigs) -> callback on the Gigs.find call, rather than the return value for the getGigsData. It's all about scopes.

由于数据库内容是异步的,因此我们需要使getGigsData异步.为此,我们将extendTemplateData: (opts) ->更改为extendTemplateData: (opts,next) ->以使其异步,然后将opts.templateData["getGigsData"] = @getGigsData()更改为return @getGigsData(opts,next)

As the database stuff is asynchronous, we need to make getGigsData asynchronous. To do this, we change extendTemplateData: (opts) -> to extendTemplateData: (opts,next) -> to make it asynchronous, and change opts.templateData["getGigsData"] = @getGigsData() to simply return @getGigsData(opts,next)

现在,我们有了事件并调用了异步方法.现在,我们需要使getGigsData的定义支持它.因此,让我们将getGigsData: (opts) ->更改为getGigsData: (opts,next) ->来接受在步骤3中定义的完成回调(next).我们要做的是,在具有return gigs的位置调用下一步,因此让return gigsreturn next()

Now that we have the event and call asynchronous. We now need to make the definition of getGigsData support it. So lets change getGigsData: (opts) -> to getGigsData: (opts,next) -> to take in the completion callback (next) that we defined in step 3. And what we will do, is we will call next where we have return gigs, so lets change return gigs to return next()

它现在应该可以工作了.但是,作为一点清理,我们可以通过将if err then console.error "db error"更改为return next(err) if err来使错误处理更好.您需要修复缩进,因为我们需要删除else块.

It should now work. But as a little bit of cleaning, we can make the error handling better by changing if err then console.error "db error" to return next(err) if err. You will need to fix up the indentation as we will need to remove the else block.

考虑所有这些,并进行更多清洁,您将得到以下结果:

Considering all that, and with a bit more cleaning applied, you'll end up with this:

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
        @

这篇关于Docpad:通过猫鼬回调使用extendTemplateData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆