一、回调函数
node 的所有API都支持回调函数。阻塞是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,就需要些在函数内。
- node 是单进程单线程应用程序,单因为 V8 引擎提供的异步执行回调接口,可以处理大量的并发,性能很高。
- 几乎所有的事件机制都是观察者模式实现;
- 每一个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数;
- 执行异步操作的函数将回调函数作为最后一个参数,回调函数接收错误对象作为第一个参数
二、事件驱动
- web server 可以一直接受请求而不等待任何读写操作:称之为非阻塞IO或者事件驱动IO;
- 在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数;
- nodejs 所有异步io操作在完成时都会发送一个事件到事件队列
- 只要是支持事件响应的核心模块都是 EventEmiiter 的子类
var events = require("events");var eventEmitter = new events.EventEmitter();// 定义事件观察者、监听器、或者叫处理器var eventHandler = function handler(){ ???console.log("handle event")}// 事件注册var eventEmitter.on("demo", eventHandler);// 事件发布var eventEmitter.emit("demo")
三、buffer
buffer类用来创建一个专门存放二进制数据的缓冲区,buffer类似于一个整数数组。
3.1、支持的字符编码
- ascii
- utf8
- uft16le
- ucs2
- base64
- latin1
- binary
- hex : 一个字节(8 bit)编码为两个十六进制字符
3.2、创建Buffer类
- Buffer.alloc
- Buffer.allocUnsafe
- Buffer.allocUnfaseSlow
- Buffer.from
3.3、写缓冲区
- buf.write
3.4、读缓冲区
- buf.toString
- buf.toJSON()
四、Stream
- http 服务器发起请求的 request 对象就是一个 Stream,stdout 也是一个Stream
- Stream 对象都是 EventEmitter 实例,常用事件:data,end,error,finish
- 四种类型: Readable,Writable,Duplex,Transform
- 管道流:从一个流中获取数据并将数据传递到另外一个流中;
- 链式流:
五、模块系统
模块是为了更好的代码服用,文件和模块一一对应,可以是 js 代码,json,或者 c/c++ 扩展;
模块创建的两种方式: exports, module.exports
exports.world = function () { ???console.log("hello world!")}
function Hello() { ????var name; ????this.setName = function(thyName) { ????????name = thyName; ????}; ????this.sayHello = function() { ????????console.log(‘Hello ‘ + name); ????}; }; module.exports = Hello;
使用模块:require
var hello = require(‘hello‘);hello.world()
var Hello = require(‘./hello‘); hello = new Hello(); hello.setName(‘BYVoid‘); hello.sayHello();
- 模块类型:原生模块(http, fs, path, os…), 相对路径文件模块,绝对路径文件模块,文件模块
- 模块加载顺序: 原生模块 > 文件模块, 优先从缓存中加载,缓存中没有则从文件加载,并保存到缓存中。
六、函数
- js 中的函数是第一类对象,可以作为参数或返回值
- 匿名函数与lambda表达式:以更简洁的形式进行函数对象的传递
function hello(say) { ???say();}hello(function(){ ???console.log("hello node!");})hello(()=> console.log("hello lambda!"))
七、路由
- 输入信息: url, get/post query parameters, request body
- 在 web server 接收到新的 request 时,会解析输入信息,并分发给特定的处理器,这里的分发工作就是“路由”
a simple http server
var http = require("http");var url = require("url");function route(request){ ???return url.parse(request.url).pathname;}http.createServer((request, response) => { ???response.writeHead(200, {"Content-Type": "text/plain"}); ???response.write(route(request)); ???response.end();}).listen(8888);
- url.parse
{ ???protocol: null, ???slashes: null, ???auth:null, ???host: null, ???port: null, ???hostname: null, ???hash: null, ???search: "?name=xxxxx&url=aaaaa", ???query: { ???????name: ‘xxxxx‘, ???????url: ‘aaaaa‘ ???}, ???pathname: ‘/user‘, ???path: ‘/username=xxxxx&url=aaaaa?‘, ???href: ‘name=xxxxx&url=aaaaa‘}
- 接收请求体:请求体传输是一件耗时的工作,需要异步接收
var http = require(‘http‘);var querystring = require(‘querystring‘);http.createServer(function(req, res){ ???// 定义了一个post变量,用于暂存请求体的信息 ???var post = ‘‘; ????????// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中 ???req.on(‘data‘, function(chunk){ ???????????post += chunk; ???}); ???// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。 ???req.on(‘end‘, function(){ ???????????post = querystring.parse(post); ???????res.end(util.inspect(post)); ???});}).listen(3000);
八、全局对象
- node 中的全局对象名为 global,浏览器中的全局对象名为 window
- 务必通过 var 来定义变量,因为未定义直接赋值的变量(隐式变量)会被视为全局变量;
- __filename, __dirname,
- setTimeout(cb, ms), clearTimeout(t), setInterval(cb, ms)
- console: log, info, error, warn, dir, time, timeEnd, trace, assert
当 console.log 接收到多个参数时,会进行格式化输出:
console.log(‘Hello world‘); ?// Hello worldconsole.log(‘byvoid%diovyb‘); // byvoid%diovyb console.log(‘byvoid%diovyb‘, 1991); ?//byvoid1991iovyb
- process 属性: stdout, stderr, stdin, argv, execPath, execArgv, env, config, pid, title
- process 方法: abort, chdir, cwd, exit, getgid, setgid, getuid, setdui, kill, uptime …
九、Node.js常用工具
- util.inherits: 实现js对象间的原型继承
- util.inspect: 将任意对象转换为字符串
- util.isArray(object)
- util.isData(obj)
- OS,Path,net ,dns,domain
十、文件系统
var fs = require("fs");fs.readFile("filename", (err, data)=> { ???console.log("read file");})
- fs.open(path, flags[, mode], callback)
- fs.stat(path, callback)
- fs.writeFile(file, data[, options], callback)
- fs.read(fd, buffer, offset, length, position, callback)
- fs.close(fd, callback)
- fs.ftruncate(fd, len, callback)
- fs.unlink(path, callback) : 删除文件
- fs.mkdir(path[, mode], callback)
- fs.readdir(path, callback)
- fs.rmdir(path, callback)
十一、Express框架
Express 是一个简洁而灵活的应用框架。
var express = require(‘express‘);var app = express();app.get(‘/‘, function (req, res) { ??res.send(‘Hello World‘);})var server = app.listen(8081, function () { ?var host = server.address().address ?var port = server.address().port ?console.log("应用实例,访问地址为 http://%s:%s", host, port)})
11.1、Request对象
- req.app : 访问 express 实例
- req.baseUrl
- req.body/req.cookies
- req.fresh/req.stale
- req.hostname/req.ip
- req.originalUrl
- req.params
- req.path
- req.protocol
- req.query
- req.route
- req.subdomains
- req.accepts()
- req.acceptsCharsets/req.acceptsEncodings/req.acceptsLanguages
- req.get() : 获取指定的 HTTP 请求头
11.2、 Response对象
- res.app
- res.append()
- res.set()
- res.cookie(name, value [, option])
5. - res.clearCookie()
- res.download()
- res.get()
- res.json()
- res.jsonp()
- res.location()
- res.redirect()
- res.render(view, [locals], callback)
- res.send()
- res.sendFile()
- res.set()
- res.status()
- res.type()
11.3、路由
var express = require(‘express‘);var app = express();// ?主页输出 "Hello World"app.get(‘/‘, function (req, res) { ??console.log("主页 GET 请求"); ??res.send(‘Hello GET‘);})// ?POST 请求app.post(‘/‘, function (req, res) { ??console.log("主页 POST 请求"); ??res.send(‘Hello POST‘);})// ?/del_user 页面响应app.get(‘/del_user‘, function (req, res) { ??console.log("/del_user 响应 DELETE 请求"); ??res.send(‘删除页面‘);})// ?/list_user 页面 GET 请求app.get(‘/list_user‘, function (req, res) { ??console.log("/list_user GET 请求"); ??res.send(‘用户列表页面‘);})// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求app.get(‘/ab*cd‘, function(req, res) { ?????console.log("/ab*cd GET 请求"); ??res.send(‘正则匹配‘);})var server = app.listen(8081, function () { ?var host = server.address().address ?var port = server.address().port ?console.log("应用实例,访问地址为 http://%s:%s", host, port)})
11.4、静态文件
可以使用 express.static 中间件来设置静态文件路径:
app.use(express.static(‘public‘));
11.5、文件上传
html><head><title>文件上传表单</title></head><body><h3>文件上传:</h3>选择一个文件上传: <br /><form action="/file_upload" method="post" enctype="multipart/form-data"><input type="file" name="image" size="50" /><br /><input type="submit" value="上传文件" /></form></body></html>
服务端代码:
var express = require(‘express‘);var app = express();var fs = require("fs");var bodyParser = require(‘body-parser‘);var multer ?= require(‘multer‘);app.use(express.static(‘public‘));app.use(bodyParser.urlencoded({ extended: false }));app.use(multer({ dest: ‘/tmp/‘}).array(‘image‘));app.get(‘/index.htm‘, function (req, res) { ??res.sendFile( __dirname + "/" + "index.htm" );})app.post(‘/file_upload‘, function (req, res) { ??console.log(req.files[0]); ?// 上传的文件信息 ??var des_file = __dirname + "/" + req.files[0].originalname; ??fs.readFile( req.files[0].path, function (err, data) { ???????fs.writeFile(des_file, data, function (err) { ????????if( err ){ ?????????????console.log( err ); ????????}else{ ??????????????response = { ??????????????????message:‘File uploaded successfully‘, ???????????????????filename:req.files[0].originalname ?????????????}; ?????????} ?????????console.log( response ); ?????????res.end( JSON.stringify( response ) ); ??????}); ??});})var server = app.listen(8081, function () { ?var host = server.address().address ?var port = server.address().port ?console.log("应用实例,访问地址为 http://%s:%s", host, port)})
12.6、 cookie管理
可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:
var express ?????= require(‘express‘)var cookieParser = require(‘cookie-parser‘)var util = require(‘util‘);var app = express()app.use(cookieParser())app.get(‘/‘, function(req, res) { ???console.log("Cookies: " + util.inspect(req.cookies));})app.listen(8081)
十二、数据库
nodejs知识结构
原文地址:https://www.cnblogs.com/LYL-8/p/9639461.html