app.use(function (req, res) {
getData.d1(function (err, s1data) {
getData.d2(function (err, s2data) {
res.render('layout', {
s1: temp.s1(s1data)
, s2: temp.s2(s2data)
})
})
})
})
这样也可以得到我们想要的结果,但是这样的话,要足足 8 秒才会返回。
其实实现逻辑可以看出 getData.d2 是在 getData.d1 的结果返回后才开始调用,而它们两者并没有这样的依赖关系。我们可以用如 async 之类的处理 JavaScript 异步调用的库来解决这样的问题,不过我们这里就简单手写吧:
复制代码 代码如下:
app.use(function (req, res) {
var n = 2
, result = {}
getData.d1(function (err, s1data) {
result.s1data = s1data
--n || writeResult()
})
getData.d2(function (err, s2data) {
result.s2data = s2data
--n || writeResult()
})
function writeResult() {
res.render('layout', {
s1: temp.s1(result.s1data)
, s2: temp.s2(result.s2data)
})
}
})
这样就只需 5 秒。
在接下来的优化之前,我们加入 jquery 库并把 css 样式放到外部文件,顺便,把之后我们会用到的浏览器端使用 jade 模板所需要的 runtime.js 文件也加入进来,在包含 app.js 的目录下运行:
复制代码 代码如下:
mkdir static
cd static
curl -o jquery.js
ln -s ../node_modules/jade/runtime.min.js jade.js
并且把 layout.jade 中的 style 标签里的代码拿出来放到 static/style.css 里,然后把 head 标签改为:
复制代码 代码如下:
head
title Hello, World!
link(href="/static/style.css",)
script(src="/static/jquery.js")
script(src="/static/jade.js")
在 app.js 里,我们把它们两者的下载速度都模拟为两秒,在app.use(function (req, res) {之前加入:
复制代码 代码如下:
var static = express.static(path.join(__dirname, 'static'))
app.use('/static', function (req, res, next) {
setTimeout(static, 2000, req, res, next)
})
受外部静态文件的影响,我们的页面现在的加载时间为 7 秒左右。
如果我们一收到 HTTP 请求就把 head 部分返回,然后两个 section 等到异步操作结束后再返回,这是利用了 HTTP 的分块传输编码机制。在 node.js 里面只要使用 res.write() 方法就会自动加上 Transfer-Encoding: chunked 这个 header 了。这样就能在浏览器加载静态文件的同时,node 服务器这边等待异步调用的结果了,我们先删除 layout.jade 中的这 section 这两行:
复制代码 代码如下:
section#s1!=s1
section#s2!=s2
因此我们在 res.render() 里也不用给 { s1: …, s2: … } 这个对象,并且因为 res.render() 默认会调用 res.end(),我们需要手动设置 render 完成后的回调函数,在里面用 res.write() 方法。layout.jade 的内容也不必在 writeResult() 这个回调函数里面,我们可以在收到这个请求时就返回,注意我们手动添加了 content-type 这个 header:
复制代码 代码如下:
app.use(function (req, res) {
res.render('layout', function (err, str) {
if (err) return res.req.next(err)
res.setHeader('content-type', 'text/html; charset=utf-8')
res.write(str)
})
var n = 2
getData.d1(function (err, s1data) {
res.write('<section>' + temp.s1(s1data) + '</section>')
--n || res.end()
})
getData.d2(function (err, s2data) {
res.write('<section>' + temp.s2(s2data) + '</section>')
--n || res.end()
})
})