[Node入门] => 读书笔记(二)
来源:互联网 发布:好的数据恢复软件 编辑:程序博客网 时间:2024/06/09 17:37
相关笔记
- [Node入门] => 读书笔记(一)
学习内容
- 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)。
- [Node入门] => 读书笔记(二)
- [Node入门] => 读书笔记(一)
- [Node入门] => 读书笔记(三)
- 读书笔记之-node入门
- 《Node入门》读书笔记
- 从零开始node.js入门项目(二)
- MySQL数据库入门--读书笔记(二)
- Node.js 入门之二
- Node.js-入门二--进程
- Node.js初体验之入门(二)
- Node.js教程(二)入门阶段的一些坑
- node入门(二)-- 模块系统/cheerio/webSocket
- Node.js学习笔记(二)入门指南
- 入门到放弃node系列之网络模块(二)
- Node.js入门(二)——简单读写文件
- Node.js入门小记(二)node.js的模块管理
- 算法竞赛入门经典读书笔记(二)7.1简单枚举
- 算法竞赛入门经典读书笔记(二)7.1简单枚举
- 身份证号码编码方法及校验算法
- 【高斯消元】[SGU275]To xor or not to xor
- ubuntu需要额外安装的包用于支持android sdk的运行
- Git使用教程
- PHP文件上传
- [Node入门] => 读书笔记(二)
- HDOJ 5615 Jam's math problem
- Java将json数据导入到excel
- redis 链表操作
- 使用AngularJS创建应用的5个框架
- Android属性动画赏析
- dummy-----Remove Linked List Elements
- hibernate-----模拟hibernate原理
- java.io.IOException: open failed: EACCES (Permission denied)问题解决