[Node入门] => 读书笔记(二)

来源:互联网 发布:好的数据恢复软件 编辑:程序博客网 时间:2024/06/09 17:37

相关笔记

  1. [Node入门] => 读书笔记(一)

学习内容

  1. Node入门

学习笔记

1. 以非阻塞操作进行请求响应

直接借用原标题,这部分我觉得属于NodeJs的特点。毕竟,其以异步非阻塞而闻名,虽然到现在为止,我还不太了解到底是什么意思,最直接的感受就是,在此之前,我一直以为非阻塞属于nodejs必然的,并没有想到,需要自己去实现,不去通过回调函数实现,nodejs一样会阻塞。

[Node入门] 现在我们采用如下这种新的实现方式:相对采用将内容传递给服务器的方式,我们这次采用将服务器“传递”给内容的方式。 从实践角度来说,就是将response对象(从服务器的回调函数onRequest()获取)通过请求路由传递给请求处理程序。 随后,处理程序就可以采用该对象上的函数来对请求作出响应。

简单来说,将response作为参数从服务器模块(server.js)传递给路由模块(router.js),再进入请求处理模块(requestHandlers.js)生成对应的response。

如下代码:

/* [index.js]  主文件 */var server = require('./server.js');var router = require('./router.js');var requestHandlers = require('./requestHandlers.js');var handles = {};handles['/'] = requestHandlers.start;handles['/start'] = requestHandlers.start;handles['/upload'] = requestHandlers.upload;handles['/sleep'] = requestHandlers.sleep;server.start(router.route, handles);
/* [server.js] 服务器模块 */const http = require('http'); // 使用require指令载入http模块const url = require('url'); // 载入url模块const hostname = '127.0.0.1'; // 创建主机名const port = 1337; // 创建端口function start(route, handles) {    http.createServer((request, response) => {        var pathname = url.parse(request.url).pathname;        console.log(`Request for ${pathname} received.`);        route(handles, pathname, response);    }).listen(port, hostname, () => {        console.log(`Server running at http://${hostname}:${port}/`);    });}exports.start = start;
/* [router.js] 路由模块 */function route(handle, pathname, response) {    console.log(`About to route a request for ${pathname}`);    // 判断是否存在路径名,不存在则返回404错误    if (typeof handle[pathname] === 'function') {        handle[pathname](response);     } else {        console.log(`No request handler found for ${pathname}`);        response.writeHead(404, {'Context-Type' : 'text/plain'});        response.end('404 NOT FOUND');    }}exports.route = route;
/* [requestHandlers.js] 请求处理模块 */// 导入child_process模块的exec方法,使用该方法尝试非阻塞操作const exec = require('child_process').exec;// 非阻塞操作function start(response) {    console.log('Request handler "start" was called!');    // 异步非阻塞操作    exec('find /',         // 提供十秒的延迟        { timeout: 10000, maxBuffer: 20000 * 1024 },         // 异步非阻塞的核心,回调函数        (error, stdout, stderr) => {            response.writeHead(200, { 'Content-Type': 'text/plain' });            response.end(stdout);        });}function upload(response) {    console.log('Request handler "upload" was called!');    response.writeHead(200, { 'Content-Type': 'text/plain' });    response.end('Hello Upload!');}// 阻塞操作function sleep(response) {    var sleepTime = 10000, // 休眠时间        startTime = new Date().getTime();    // 休眠sleepTime毫秒,将会阻塞服务器10秒    while (new Date().getTime() < startTime + sleepTime);    response.writeHead(200, { 'Content-Type': 'text/plain' });    response.end(`Hello sleep ${sleepTime / 1000} seconds!`);}exports.start = start;exports.upload = upload;exports.sleep = sleep;

解释:在requestHandlers.js中,start()与sleep()方法的对比,可以通过进行对照试验了解。
1. 先开http://127.0.0.1:1337/start,后开http://127.0.0.1:1337/upload;
2. 先开http://127.0.0.1:1337/sleep, 后开http://127.0.0.1:1337/upload。
第一组中,start网页需要等待十秒,而upload网页能够立即得到响应;
第二组中,sleep网页同样需要等待十秒,同时阻塞了upload网页的响应。

2. 处理POST请求

实现这样一个需求:我们显示一个文本区(textarea)供用户输入内容,然后通过POST请求提交给服务器。最后,服务器接受到请求,通过处理程序将输入的内容展示到浏览器中。

/* [index.js]  主文件 */const server = require('./server.js'); // 导入服务器模块const router = require('./router.js'); // 导入路由模块const requestHandlers = require('./requestHandlers.js'); // 导入请求处理模块const handle = {}; // 创建请求对象handle['/'] = requestHandlers.start;handle['/start'] = requestHandlers.start;handle['/upload'] = requestHandlers.upload;server.start(router.route, handle);

服务器模块:与上一节对比,多了一项对于返回数据的处理,这是因为

[Node入门] 为了使整个过程非阻塞,Node.js会将POST数据拆分成很多小的数据块,然后通过触发特定的事件,将这些小数据块传递给回调函数。这里的特定的事件有data事件(表示新的小数据块到达了)以及end事件(表示所有的数据都已经接收完毕)。

/* [server.js] 服务器模块 */const http = require('http'); // 使用require指令载入http模块const url = require('url'); // 载入url模块const hostname = '127.0.0.1'; // 创建主机名const port = 1337; // 创建端口function start(route, handle) {    http.createServer((request, response) => {        var postData = '';        // 获取请求中的url路径        var pathname = url.parse(request.url).pathname;        console.log(`Request for ${pathname} received.`);        // 设置接受的数据编码格式为UTF-8        request.setEncoding('utf8');        // 监听请求的‘data’事件        // 因为接受的数据可能会很大,为了使整个过程非阻塞,Node.js会将POST数据拆分成很多小的数据块        request.on('data', postDataChunk => postData += postDataChunk);        // 监听请求的‘end’事件,确保它只会当所有数据接受完毕后才触发        request.on('end', () => route(handle, pathname, response, postData));    }).listen(port, hostname, () => { // 监听主机,端口        console.log(`Server running at http://${hostname}:${port}/`);    });}exports.start = start;

请求处理模块: /start 返回了一个包含文本区的html,并在点击上传后,将数据显示到 /upload。

/* [requestHandlers.js] 请求处理模块 */const querystring = require('querystring');function start(response, postData) {    console.log('Request handler "start" was called!');    var body = `<!DOCTYPE html>    <html>    <head>        <meta charset="UTF-8">        <title>Node入门-图片上传</title>    </head>    <body>        <form action="/upload" method="post">            <textarea name="text" rows="20" cols="60"></textarea>            <input type="submit" value="上传"></input>        </form>    </body>    </html>    `;    response.writeHead(200, { 'Content-Type' : 'text/html'});    response.end(body);}function upload(response, postData) {    console.log('Request handler "upload" was called!');    response.writeHead(200, {        'Content-Type': 'text/html;charset=utf-8'    });    response.end(`您刚刚发送的内容为:${querystring.parse(postData).text}`);}exports.start = start;exports.upload = upload;
/* [router.js] 路由模块 */function route(handle, pathname, response, postData) {    console.log(`About to route a request for ${pathname}`);    // 判断是否存在路径名,不存在则返回404错误    if (typeof handle[pathname] === 'function') {        handle[pathname](response, postData);     } else {        console.log(`No request handler found for ${pathname}`);        response.writeHead(404, {'Context-Type' : 'text/plain'});        response.end('404 NOT FOUND');    }}exports.route = route;

注意:这里有两点需要注意:
1. request的编码格式要设置成”utf8”;
2. 因为post请求是通过URL,因此需要对传入的postData进行URL解码,使用querystring模块的parse()方法(NodeAPI)。

0 0
原创粉丝点击