1.Node.js介绍与起步
1.Node.js 介绍
1.1 node.js 是什么
-
Node.js 是什么
-
JavaScript 运行时
-
既不是语言,也不是框架,它是一个平台
-
Nodejs可以解析和执行JavaScript代码
-
以前只有浏览器可以解析JavaScript代码,有了NodejsJavaScript可以完全脱离浏览器来运行
-
-
浏览器中的JavaScript
-
EcmaScipt
-
BOM
-
DOM
-
-
Node.js 中的 JavaScript
-
没有 BOM、DOM,服务端不操作页面
-
EcmaScript 基本的 JavaScript 语言部分
-
在 Node 中为 JavaScript 提供了一些服务器级别的 API
-
文件操作的能力
-
http 服务的能力
-
-
-
构建于Chrome的V8引擎之上
-
代码只是具有特定格式的字符串而已
-
引擎可以认识它,引擎可以帮助你去解析和执行
-
Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的
-
Node.js的作者把Google Chrome中的V8引擎移植了出来,开发了一个独立的JavaScipt运行时环境
-
-
Nodejs使用event-driven事件驱动, non-blocking I/O model非阻塞IO模型(异步)使其轻量而高效
-
npm是世界上最大的开源生态系统,绝大多数JavaScript的包都存放在了npm上,这样做的目的是让开发人员更方便的去下载使用。
1.2 Node.js 能做什么
-
Web服务器后台
-
命令行工具
-
npm(基于node开发的)
-
git(基于c语言开发)
-
hexo(基于node开发)
-
-
游戏服务器、接口服务器等。。
-
对于前端开发工程师来说,接触node最多的是它的命令行工具
-
自己写的很少,主要使用别人第三方开发的
-
webpack
-
gulp
-
npm
-
-
1.3 node.js 能学到啥
-
B/S编程模型
-
Browser-Server(back-end)
-
任何服务端技术这种BS编程模型都是一样的,和语言无关
-
Node只是我们学习BS编程模型的一个工具而已
-
-
模块化编程
-
RequireJS
-
SeaJS
-
@import('文件路径')
-
以前认知的JavaScript中只能通过script标签来加载
-
在Node中可以像
@import
一样来引用加载JavaScript脚本文件
-
-
Node常用的API
-
文件操作
-
http服务器构建
-
-
异步编程
-
回调函数
-
Promise
-
async
-
generator
-
-
Express Web开发框架
-
ES6
-
学习Node不仅会帮助大家打开服务端黑盒子,同时帮助你学习以后的前端高级内容
-
Vue.js
-
React
-
angular
-
2. 起步
2.1 安装node环境
2.2 HelloWord
-
创建编写JavaScipt脚本文件
-
打开终端,定位到脚本文件所属目录
-
使用输入
node 文件名
执行对应的文件
注意:文件名不要使用node.js
命名
-
解析执行 JavaScipt文件
-
读写文件
-
http
2.3 读取文件
-
使用require方法加载fs核心模块
var fs= require('fs')
-
读文件方法
fs.readFile(filePath,function(error,data){回调处理方法})
-
【param1】filePata:要读取的文件路径
-
【param2】function:回调函数
-
读取结果:
-
读取成功:data->数据,error->null
-
读取失败:data->undefine没有数据,error->错误对象
-
-
注意:读取文件中data存储的是二进制数据,通过 toString 方法转换。
-
2.4 写入文件
-
使用require方法加载fs核心模块
var fs= require('fs')
-
写文件方法
fs.writeFile(filePath,fileContent,function(error){回调处理方法})
-
【param1】filePata:要写入的文件路径
-
【param2】fileContent:要写入的文件内容
-
【param3】function:回调函数
-
读取结果:
-
写入成功:error->null
-
写入失败:error->错误对象
-
-
2.5 HTTP请求
-
加载http核心模块
var http=require('http')
-
使用http.createServer() 方法创建一个Web服务器,返回一个Server实例
var server=http.creatServer()
服务器用于提供对数据的服务:
-
发送请求
-
接收请求
-
处理请求
-
发送响应
-
-
注册request请求事件,当服务器收到请求,就会自动触发request请求事件,执行回调处理函数
server.on('request',function(){回调处理方法})
-
【param1】'request':注册事件类型为请求事件
-
【param2】function:回调函数
-
-
绑定端口号,启动服务器
server.listen(port,function(){回调处理方法})
-
【param1】port:端口号
-
【param2】function:回调函数
-
最简单的http服务:
//1. 加载 http 核心模块
var http = require('http')
// 2. 创建一个 Web 服务器返回一个 Server 实例
var server = http.createServer()
// 3. 注册 request 请求事件,监听客户端请求
server.on('request', function () {
console.log('收到客户端的请求了')
})
// 4. 绑定端口号,启动服务器
server.listen(3000, function () {
console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})
2.6 HTTP请求与响应
- 注册request请求事件,当服务器收到请求,就会自动触发request请求事件,执行回调处理函数
server.on('request',function(request,response){回调处理方法})
-
request请求事件函数,需要接受两个参数:
-
Request 请求对象:可以用来获取客户端的一些请求信息,如请求路径
request.url
-
Response响应对象:可以用来给客户端发送响应消息
response对象的write方法可以用来给客户端响应数据,write方法可以调用多次,但是要使用end方法结束响应,否则客户端会一直等待
-
-
根据不同的请求路径发送不同的响应结果
(1) 获取处理路径
req.url获取到的是端口之后的那一部分路径,所有的url都是以 / 开头的
(2) 判断路径处理响应
//1. 加载 http 核心模块
var http = require('http')
// 2. 创建一个 Web 服务器返回一个 Server 实例
var server = http.createServer()
// 3. 注册 request 请求事件,监听客户端请求,根据不同的请求路径发送不同响应结果
server.on('request', function (req,res) {
var url=req.url
if(url==='/'){
res.end('index page')
}else if(url==='/login'){
res.end('login page')
}else{
res.end('404 not found!')
}
})
// 4. 绑定端口号,启动服务器
server.listen(3000, function () {
console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})
3. Node 中的 JavaScript
-
没有DOM和BOM的EcmaScript
-
核心模块
-
第三方模块
-
用户自定义模块
3.1 核心模块
Node为JavaScipt提供了很多服务器级别的API,这些API绝大多数都被包装到了一个具名的核心模块中了。例如文件操作的fs
核心模块,http服务构建的http
模块,path
路径操作模块,os
操作系统信息模块,等等。
使用核心模块:
var fs = require('fs')
var http = require('http')
var os = require('os')
详细API文档见:http://nodejs.cn/api/
3.2 用户自定义模块
用户自己编写的文件模块
-
加载:
var foo=require('./b.js')
或者var foo=require('./b')
-
相对路径必须加 ./ 代表路径,不能省略,否则报错
-
可以省略后缀名
-
作用域:在Node中,没有全局作用域,只有模块作用域。
-
外部访问不到内部,内部也访问不到外部。
-
模块与模块通信需要用exports对象导出
-
-
require方法有两个作用:
-
加载文件模块并执行里面的代码
-
拿到被加载文件模块导出的接口对象
- 在每个文件模块中都提供了一个对象 exports,exports默认是一个空对象,需要把被外部被访问的成员挂载到这个 exports对象中
-
-
导出:(b.js)
exports.foo='hello'
4. Web服务器开发
4.1. IP地址与端口号
-
ip地址用来定位计算机
-
端口号用来定位具体的应用程序
-
所有联网通信的应用程序都会占用一个端口号。
-
端口号的范围从0~65536之间
-
开发过程中,在计算机中有一些默认的端口号,最好不要去使用,使用一些简单好记的就可以了
- 例如http服务的80
-
可以开启多个服务,但是要确保不同的服务占用不同的端口号
-
请求的客户端的ip是
response.socket.remoteAddress
,请求的客户端的端口号是response.socket.remotePort
- Node.js的API已经高度封装,集成了找到当前请求的客户端的IP地址与端口号并向他发送请求或响应的功能。服务端编程不需要知道客户端的IP地址和端口号,直接编写请求响应代码即可。
- 而在客户端访问服务端的时候,浏览器会开启端口号和服务端进行通讯。所以客户端编程也不需要写开启端口号的功能
4.2. Content Type
-
在服务端默认发送的数据,其实是utf-8编码内容,但是浏览器不知道你是utf-8的编码内容,在不知道服务器响应的编码内容的情况下会按照当前操作系统的默认编码去解析,中文操作系统的默认编码是gbk,所以会出现类似解析乱码的异常。解决方法就是告诉浏览器我给你发送的内容是什么编码格式的。在http协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型。
-
当服务端需要给客户端发送文本前,设置Content-Type:
response.setHeader('Conten-Type','text/plain;charset=utf-8')
-
不同的资源对应的Conten-Type是不一样的,图片不需要指定编码格式,一般为字符数据才指定编码格式
Content-Type查询表网址:
http://tool.oschina.net/commons
补充: Node 中的其他成员
在每个模块中,除了require
、exports
等模块相关 API 之外,还有两个特殊的成员:
-
__dirname
可以用来动态获取当前文件模块所属目录的绝对路径 -
__filename
可以用来动态获取当前文件的绝对路径 -
__dirname
和__filename
是不受执行 node 命令所属路径影响的
在文件操作中,使用相对路径是不可靠的。因为文件操作路径中,相对路径 (./xxx
) 设计的是相对于执行 node 命令所处的路径, 不是当前文件所处的路径。
例如:
// 这里的 ./a.txt 是相对于执行代码文件的 node 命令行所处路径,不是代码文件的所处路径
fs.readFile('./a.txt', 'utf8', function (err) {
if (err) {
throw err
}
console.log(data)
})
所以为了解决这个问题,只需要把相对路径变成绝对路径就可以了。
那我们可以使用__dirname
或者 __filename
来帮我们解决这个问题。
在拼接路径的过程中,为了避免手动拼接带来的一些低级错误,所以推荐多使用:path.join
来辅助拼接。
所以为了进尽量避免使用相对路径不可靠的问题,在文件操作中使用相对路径都统一转换为 动态绝对路径。
fs.readFile(path.join(__dirname, './a.txt'), 'utf8', function (err) {
if (err) {
throw err
}
console.log(data)
})
注意:模块中的路径标识和文件操作中的相对路径标识不一致,模块中的路径标识就是相对于当前文件模块,不受执行 node 命令所处路径影响。例如:
require('./b')