ejs 是常用的模版引擎之一,co-ejs 是经过改造 ejs 源码以支持生成器函数的一种尝试。我们通常所理解的模板引擎是将定义好的模版与静态数据(如JSON)结合渲染生成 HTML ,而有了co-ejs,我们可以做些更有意思的事情,我们来看 co-ejs 的 example :
app.js
var path = require('path');
var app = require('koa')();
var wait = require('co-wait');
var render = require('co-ejs');
var locals = {
version: '1.0.0',
now: function () {
return new Date();
},
ip: function *() {
yield wait(1000);
return this.ip;
},
callback: function() {
return function (cb) {
cb(null, '<p>callback</p>');
}
},
callbackGen: function() {
return function* () {
yield wait(3000);
return '<p>callbackGen</p>';
};
},
doNothing: function() {
console.log('this will not print');
}
};
var filters = {
format: function (time) {
return time.getFullYear() + '-' + (time.getMonth() + 1) + '-' + time.getDate();
}
};
app.use(render(app, {
root: path.join(__dirname, 'views'),
layout: 'layout',
viewExt: 'html',
cache: true,
debug: true,
locals: locals,
filters: filters
}));
app.use(function *() {
console.time('time');
yield this.render('content', {
users: [{name: 'John'}, {name: 'Jack'}, {name: 'Tom'}]
});
console.timeEnd('time');
});
app.listen(3000, function () {
console.log('listening on 3000.');
});
content.html
<div>
<p>version: <%= version %></p>
<p>now: <%=: now() | format %></p>
<p>ip: <%= ip %></p>
<% var cb = yield callback() %>
<p>callbackGen: <%= callbackGen() %></p>
<p>callback: <%- cb %></p>
<p><%=: users | map : 'name' | join %></p>
<% include user.ejs %>
</div>
可以看出,在 co-ejs 中,我们不仅可以传入一个普通变量、函数,甚至可以直接在模版中使用生成器函数、生成器以及 yield。 co-ejs 会将以 <%= %> 或 <%- %> 包裹的表达式并行执行,即 ip 函数延时 1s 执行结束,callbackGen 函数延时 3s 结束,最终渲染模版只需 3s。而在 <% %> 内使用 yield 则会顺序执行,假如将上例中的 callback 函数修改为:
callback: function() {
return function (cb) {
setTimeout(function () {
cb(null, '<h1>callback</h1>');
}, 2000);
};
}
则渲染模版需要花 5s。