跳到主要内容

Node.js

globalprocess 对象

在 Node.js 中,唯一的全局对象称为 global,这个对象的属性和方法可以通过 console.log(console) 查看。而 process 对象则代表当前的进程:

> process === global.process;
true
> process.version;
'v5.2.0'
> process.platform;
'darwin'
> process.arch;
'x64'
> process.cwd(); //返回当前工作目录
'/Users/michael'
> process.chdir('/private/tmp'); // 切换当前工作目录
undefined
> process.cwd();
'/private/tmp'

我们可以在下一次事件响应中执行代码,通过 process.nextTick() 方法:

process.nextTick(function () {
console.log('nextTick callback!');
});
console.log('nextTick was set!');

我们也可以用 exit 事件来让程序退出时执行某个函数。

fs 同步读写文件

var fs = require('fs');
var data = fs.readFileSync('163.yaml');
fs.writeFileSync('test.yaml', data)

fs 读写流

流是有顺序的数据。在 Node.js 中,流是一个对象,我们需要响应流的事件:

'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
console.log('DATA:')
console.log(chunk);
});

rs.on('end', function () {
console.log('END');
});

rs.on('error', function (err) {
console.log('ERROR: ' + err);
});

而以流的形式写入文件需要调用 write() 方法并以 end() 结束:

'use strict';

var fs = require('fs');

var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();

pipe 对接

我们可以将可读流和可写流串起来:

'use strict';

var fs = require('fs');

var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');

rs.pipe(ws);

这样,我们可以完成文件的复制。

http 服务器

我们可以通过 http 模块的 requestresponse 处理请求:

'use strict';

var http = require('http');
var server = http.createServer(function (request, response) {
console.log(request.method + ': ' + request.url);
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello world!</h1>');
});

server.listen(8080);
console.log('Server is running at http://127.0.0.1:8080/');

文件服务器

首先我们将 URL 解析,然后找到对应的路径就可以了。在返回文件的时候,我们不需要读取文件,只需要将它对接上 response 这个流即可:

var server = http.createServer(function (request, response) {
var pathname = url.parse(request.url).pathname;
var filepath = path.join(root, pathname);
fs.stat(filepath, function (err, stats) {
if (!err && stats.isFile()) {
console.log('200 ' + request.url);
response.writeHead(200);
fs.createReadStream(filepath).pipe(response);
// 因为自动关闭,所以不需要手动关闭。
} else {
console.log('404 ' + request.url);
response.writeHead(404);
response.end('404 Not Found');
}
});
});

koa 中间件

http 的请求由多个中间件组成的处理链组成,通过不同的中间件组合我们可以实现很多功能。每个中间件通过 await next() 调用下一个函数。

app.use(async (ctx, next) => {
console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URL
await next(); // 调用下一个middleware
});

app.use(async (ctx, next) => {
const start = new Date().getTime(); // 当前时间
await next(); // 调用下一个middleware
const ms = new Date().getTime() - start; // 耗费时间
console.log(`Time: ${ms}ms`); // 打印耗费时间
});

app.use(async (ctx, next) => {
await next();
ctx.response.type = 'text/html';
ctx.response.body = '<h1>Hello, koa2!</h1>';
});

koa-router 处理不同的 URL

除了最初的一个之外,剩下的中间件都用 router 实现:

router.get('/hello/:name', async (ctx, next) => {
var name = ctx.params.name;
ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});

router.get('/', async (ctx, next) => {
ctx.response.body = '<h1>Index</h1>';
});

// add router middleware:
app.use(router.routes());

Nunjucks 模板引擎

首先定义一个环境:

var env = new nunjucks.Environment(new nunjucks.FileSystemLoader('templates'));

然后进行渲染:

env.render('home.html')

处理静态文件的中间件

let staticHandler = async (ctx, next) => {
let rpath = ctx.request.path;
if (rpath.startsWith('/static/')) {
let fp = rpath.substring(1);
if (await fs.exists(fp)) {
ctx.response.type = mime.getType(fp);
ctx.response.body = await fs.readFile(fp);
} else {
ctx.response.status = 404;
}
} else {
await next();
}
};

集成 Nunjucks 的中间件

我们利用一个中间件向 ctx 绑定渲染函数:

App.use(async (ctx, next) => {
// 给ctx绑定render函数:
ctx.render = function (view, model) {
ctx.response.body = env.render(view, Object.assign({}, ctx.state || {}, model || {}));
ctx.response.type = 'text/html';
};
await next();
})