使用Keystone视图的Nunjucks异步渲染

时间:2018-04-13 09:40:51

标签: node.js express asynchronous keystonejs nunjucks

在基于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;
});

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

2 个答案:

答案 0 :(得分:1)

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

Imho,使用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
    }
);

答案 1 :(得分:0)

我不了解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中有一个<script>标记,链接到下面显示的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...')
})

可以看出,我通过实施async并且甚至没有触及视图引擎,在浏览器和服务器之间进行fetch API通信。

我只是想提供另一种想法来使用fetch API并与它进行async HTTP通信,而不管正在使用的任何视图呈现引擎。