【nodejs】基础介绍
Node是什么?
官网定义:Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
node 是一个JavaScript运行时(runtime),所谓运行时就可以想象成一个编程语言的运行环境。
这个运行环境包括了运行代码需要的编译器(解释器)以及操作系统的底层支持等。
Node特点是什么?
单线程:单线程是Node.js保持轻量级和高性能的关键,这里的单线程是主线程为‘单线程’, 所有阻塞的部分交给一个线程池处理,然后主线程通过一个队列跟线程池协作。我们写的代码部分不用关心线程问题,代码也主要由一堆callback回调构成,然后主线程在循环过程中适时调用这些代码。单线程除了保证Node.js高性能之外,还保证了绝对的线程安全,使开发者不用担心同一变量同时被多个线程读写而造成程序崩溃。

事件循环: 通俗的来讲,事件循环就是一个程序启动期间运行的死循环,没有任何特别之处。客户端请求建立连接,提交数据等行为,会触发相应的事件,调用对应的事件处理回调函数。在Node中,一个时刻只能处理一个回调函数,但是在执行一个回调函数的中途,可以转而处理其他事件,然后继续返回执行原事件的回调函数,这种处理机制,称为‘事件环’机制。

非阻塞io: IO都是阻塞的,而Node.js却说自己是非阻塞IO,那么只能说明一点,IO肯定不是由Node.js来处理, Node.js会把IO这项工作分配给别人来做,别人IO完了,再事件通知Node.js,将IO结果重新加入排队,等待被处理
Node与Npm
在Node.js中,以模块为单位划分所有功能,并提供了一个完整的模块加载机制,这使得我们可以将应用程序划分为各个不同的部分,并且对这些部分进行很好的协同管理。通过将各种可重用代码编写在各种模块中的方法,我们可以大大减少应用程序代码量,提高应用程序的开发效率以及应用程序代码的可读性。通过模块加载机制,我们可以将各种第三方模块引入到我们的应用程序中。Node.js 提供了一个npm包管理工具,用于从第三方网站上下载各种Node.js包。
Node模块的加载
Node.js使用CommonJS规范加载模块(同步加载模块,只有模块加载完成,才能执行后面的操作)
CommonJS规范将每个文件都看作一个模块,模块内部的变量都是私有的,无法被其他模块使用,除非是用预定义的方法将内部的变量暴露出来(通过exports 和 require关键字来实现)
require引用模块示例:
// we.js 定义了一个简单的自定义模块
var we = { my: function() { console.log('I am 220...') }, you: function() { console.log('I am 284...') } } module.exports = we
这样就实现了一个自定义模块,该模块提供了一个接口,然后使用module.exports 将该接口暴露给外部使用.
var we = require('./we.js') we.my()
外部代码想要使用we.js中的方法,需要使用require关键字引入该接口。
require的缓存策略:
Node会自动缓存经过require引入的文件,使得下次再引入不需要经过文件系统而是直接从缓存中读取。
var we = require('./we.js') console.log(require.cache) // 输出内容如下,我们可以在这里找到很多有用的信息,
// 例如path表示模块引入时Node的查找路径,即从当前目录下的node_modules开始,一直到磁盘根目录为止 { 'C:\Users\wangr\Desktop\Node\main.js': Module { id: '.', exports: {}, parent: null, filename: 'C:\\Users\\wangr\\Desktop\\Node\\main.js', loaded: false, children: [ [Object] ], paths: [ 'C:\\Users\\wangr\\Desktop\\Node\\node_modules', 'C:\\Users\\wangr\\Desktop\\node_modules', 'C:\\Users\\wangr\\node_modules', 'C:\\Users\\node_modules', 'C:\\node_modules' ] }, 'C:\Users\wangr\Desktop\Node\we.js': Module { id: 'C:\\Users\\wangr\\Desktop\\Node\\we.js', exports: { my: [Function: my], you: [Function: you] }, parent: Module { id: '.', exports: {}, parent: null, filename: 'C:\\Users\\wangr\\Desktop\\Node\\main.js', loaded: false, children: [Array], paths: [Array] }, filename: 'C:\\Users\\wangr\\Desktop\\Node\\we.js', loaded: true, children: [], paths: [ 'C:\\Users\\wangr\\Desktop\\Node\\node_modules', 'C:\\Users\\wangr\\Desktop\\node_modules', 'C:\\Users\\wangr\\node_modules', 'C:\\Users\\node_modules', 'C:\\node_modules' ] } }
Node核心模块 - http模块
http模块主要提供了一系列用于网络传输的API,在http模块中,node定义了一些顶级的类、属性以及方法
创建http服务器:通常使用createServer方法创建http服务器
// 代码中使用createServer方法创建了一个简单的HTTP服务器,该方法返回一个http.server的实例,
// createServer方法包含了一个匿名的回调函数,该函数有两个参数req和res, 分别是HTTP的request和response对象,
// 服务器创建完成后,Node进程开始循环监听3000端口,
// 当浏览器访问localhost:3000时,Node返回‘Hello World’
const http = require('http') const server = http.createServer(function(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello World') }) server.listen(3000)
Rquest 请求信息对象:当处理http请求时,最先做的事就是获取请求的URL、method等信息。Node将相关信息都封装在一个对象中(回调函数中的req).
const http = require('http')
const server = http.createServer(function(req, res) {
// 再次请求localhost:3000
// 获取请求的 method
let method = req.method
console.log(method)
// => GET
// 获取请求的 URL
let url = req.url
console.log(url)
// => /
// 获取请求的 header
let headers = req.headers
console.log(headers)
// => { host: 'localhost:3000',
// connection: 'keep-alive',
// 'cache-control': 'max-age=0',
// 'upgrade-insecure-requests': '1',
// 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
// accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
// 'accept-encoding': 'gzip, deflate, br',
// 'accept-language': 'zh-CN,zh;q=0.9' }
// 获取请求的 body
let body = []
req.on('data', function(chunk) {
body.push(chunk)
}).on('end', function() {
body = Buffer.concat(body).toString()
console.log(body)
})
res.writeHead(200, {'Content-Type': 'text/plain'})
res.end('Hello World')
})
server.listen(3000)
Response 请求响应对象
设置响应头: response.setHeader 、 response.writeHead
// 使用 response.setHeader 设置响应头信息 res.setHeader('Content-Type', 'application/json') // 使用 response.setHeader方法 只能设置单个属性内容 // 使用 response.writeHead方法 一次性设置所有的响应头和状态码 res.writeHead(200, { 'Content-Length': Buffer.byteLength(body), 'Content-Type': 'text/plain' })
设置响应体: response.write、response.end
// write方法将要发送的数据 存放到流中 调用end方法将该stream发送到客户端 res.write('<html>') res.write('<body>') res.write('<h1>Hello,World</h1>') res.write('</body>') res.write('</html>') // 也可以直接将返回数据直接作为end方法的参数进行返回 res.end('<html><body><h1>Hello World</h1></body></html>')
HTTP客户端服务: HTTP模块除了能在服务端处理客户端请求之外,还可以作为客户端向服务器发起请求,
通过http.get发起get请求,通过post方法上传文件等。这也是Node也能做出桌面软件的基础
const http = require('http')
http.get('http://www.baidu.com', function(res) {
let statusCode = res.statusCode
if(statusCode === 200) {
let result = ''
res.on('data', function(data) {
result += data
})
res.on('end', function() {
console.log(result.toString())
})
res.on('error', function(e) {
console.log(e.message)
})
}
})
创建代理服务器: 代理服务器相当于在客户端和目标服务器之间建立了一个中转,所有的访问和流量都经过这个服务器进行中转,代理服务器在实际中运用十分广泛。例如,如果本地机器不能直接访问目标服务器,那么就在可以连通两端的机器上搭建一个代理服务器,就能通过间接方式访问目标服务器了
// 当我们请求localhost:8080/google.com 的时候
// 就由我们的代理服务器去请求google.com http.createServer(function(req, res) { let url = req.url.slice(1) let proxyRequest = http.request(url, function(pRes) { res.writeHead(pRes.statusCode, pRes.headers) pRes.on('data', function(data) { res.write(data) }) pRes.on('end', function() { res.end() }) }) req.on('data', function(data) { proxyRequest.write(data) }) req.on('end', function() { proxyRequest.end() }) }).listen(8080)
总结:
Node.js强大体现在事件驱动、异步处理、非阻塞IO等方面。
Node.js 擅长对数据库等IO操作频繁的系统中。
Node.js 不擅长CPU密集型的应用、模板渲染、压缩/解压缩、加/解密等操作都是Node.js的软肋

浙公网安备 33010602011771号