【问题标题】:Nunjucks Async Rendering with Keystone ViewNunjucks 使用 Keystone 视图进行异步渲染
【发布时间】:2018-09-23 15:06:51
【问题描述】:

在基于Express 的应用程序中,我正在运行一个异步函数来从数据库中获取图像源并将它们呈现到Nunjucks 视图引擎中

Nunjucks 在 DOM 中渲染以下内容

<img src="[object Promise]">

我已经有enabled Nunjucks's async renderingweb: { async: true }enabled the nunjucks async api with a callback 像这样

// controller.js (KeystoneJS app)
view.render('index', function (err, res) {
    console.log('err at index render', err); // undefined
    return res;
});

如何获得异步函数的解析值?

【问题讨论】:

    标签: node.js express asynchronous keystonejs nunjucks


    【解决方案1】:

    据我了解,Nunjucks 不直接支持异步渲染。您可以使用异步过滤器来获取它。也许我错了。

    恕我直言,使用带有Be Careful! 标记的功能不是一个好主意。


    // template.njk
    Hello {{user_id | find | attr('name') }}!
    
    // app.js
    var nunjucks  = require('nunjucks');
    var env = nunjucks.configure();
    
    // Async filter
    env.addFilter('find', function(a, cb) {
        setTimeout(function () {
            cb(null, {
                name: 'Smith'
            });
        }, 10);
    }, true)
    
    // Sync filter
    env.addFilter('attr', function(obj, attr) {
        return obj && attr && obj[attr];
    });
    
    env.render('template.njk', 
        {user_id: 1}, // pass sync vars
        function(err, res) {
            if (err)
               return;
    
            console.log(res);
            return res
        }
    );
    

    【讨论】:

    • 是的,我同意你的想法,使用过滤器而不是直接渲染。但是,我认为启用web: {async: true} 可能会启用直接异步渲染,如Nunjucks Docs 中所述
    • 恕我直言,web: ... 选项启用异步加载器,而不是渲染。
    【解决方案2】:

    我不知道nunjucks,但无论使用何种视图引擎,您都可以实现async 功能。为了展示这个想法,我试图重现你的情况。我创建了一个名为 index.html 的 HTML 文件,带有一个 img 标记,没有任何 src 属性:

    <html>
        <head>
            <meta charset="utf-8"/>
            <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
            <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
            <title>Reproduce</title>
        </head>
        <body>
            <img id='bg'></img>
            <script src='./so.js'></script>
        </body>
    </html>
    

    我的 HTML 中有一个 &lt;script&gt; 标记,它链接到我的 so.js 文件,如下所示,通过向 NodeJS/Express 服务器发送 HTTP 请求来请求图像:

    getImage();
    
    function getImage(){
    
        // Get an image by its name as URL parameter
        fetch('/bg/background.jpg',{
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        }).then(result=>{
            return result.blob()
        }).then(result=>{
            console.log('result -> ', result)
            document.querySelector('#bg').src=URL.createObjectURL(result)
            document.querySelector('#bg').style.width='200px'
        }).catch(err=>{
            console.log('err -> ', err)
        })
    }
    

    这是我在文件名server.js 中的 NodeJS/ExpressJS 代码:

    express=require('express')
    bodyParser=require('body-parser')
    path=require('path')
    fetch=require('node-fetch')
    
    server=express()
    
    //Body-parser middleware
    server.use(bodyParser.json())
    server.use(bodyParser.urlencoded({extended:false}))
    server.use(bodyParser.raw())
    
    //Set static path
    server.use(express.static(path.join(__dirname,'public')))
    
    server.get('/',(req,res)=>{
            res.render('index.html')
    })
    
    // Pick a file on hard disk
    // and  send it as "Blob" to the browser
    server.get('/bg/:name',(req,res)=>{
        var options = {
            root: __dirname + '/public/',
            dotfiles: 'deny',
            headers: {
                'x-timestamp': Date.now(),
                'x-sent': true
            }
        };
    
        var fileName = req.params.name;
        res.sendFile(fileName, options, function (err) {
            if (err) {
                next(err);
            } else {
                console.log('Sent:', fileName);
            }
        });
    })
    
    server.listen('8000',()=>{
            console.log('Server listening on port 8000...')
    })
    

    可以看出,我正在通过实现fetch API 在浏览器和服务器之间进行async 通信,甚至不接触视图引擎。

    我只是想提供一个替代想法,以使用fetch API 并与之进行async HTTP 通信,而不管正在使用任何视图渲染引擎。

    【讨论】:

    • 感谢您的回答,但我需要通过视图引擎执行此操作,因为我需要异步渲染网站中的所有图像,因此放置这些选择器对我来说太乏味了。尽管如此,对于寻找async 渲染的其他人来说,这是一个不错的选择
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    • 2012-03-06
    • 2021-12-09
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    相关资源
    最近更新 更多