Node.js简介
—学习Node.js更好地深入了解服务器端这个黑盒子,理解前后端数据交互;此外还有像Java、PHP、Python、Ruby、Net等服务端开发语言;
—Node.js是基于Chrom V8的运行时环境,不是一门语言,也不是库、框架,简单来说是可以解析和执行JavaScript代码的平台;以前只有浏览器才可以解析运行JS代码,但是现在JS可以完全脱离浏览器运行;
—Node.js的特性:事件驱动event-driven、非阻塞IO模型(异步);
—Node.js的包生态系统是npm,npm是世界上最大的开源生态系统,绝大多数JavaScript相关的包都存放在npm上,目的是为了让开发人员更加方便的去下载和使用;
—浏览器的JavaScript由ECMAScript、DOM和BOM三部分组成;
—Node.js中的JavaScript没有DOM和BOM,包含ECMAScript和为JavaScript提供一些服务级别的操作API,比如文件读写、网络服务的构建、http服务器等处理;
—JavaScript引擎帮助解析和执行JS代码,专门处理JavaScript脚本的虚拟机,一般会附带在网页浏览器之中;
—Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的;
—V8 提供了执行 JavaScript 的运行时环境。 DOM 和其他 Web 平台 API 则由浏览器提供
—Node.js把Google Chrome中的V8引擎移植出来,开发了一个独立的JavaScript运行环境;
Node.js的功能
—Web服务器后台
—命令行工具,比如npm(node)、git(C语言)、hexo(node)等;
—对于前端开发工程师来讲,接触node最多的是它的命令行工具;
学习Node.js的技能
—B/S编程模型:任何服务端技术BS编程模型都是一样的,和语言无关;Node只是作为B/S编程模型的一个工具而已;
—模块化编程:在Node中可以像
@import
一样来引用加载JavaScript脚本文件;—Node常用API
—异步编程:回调函数、Promise、asyns、generator;
—Express Web开发框架
—ECMAScript6
Node.js核心模块
—Node为JavaScrip提供了很多服务器级别的API,这些API绝大多数都被包装到一个具名的核心模块中,例如文件操作的
fs
核心模块、HTTP服务构建的http
核心模块、path
路径操作模块、os
操作系统信息模块等;可以查看官网进行查询相关核心模块的API;—通过
require
加载核心模块;
Node.js简单操作
Node运行文件
—运行js脚本文件:打开终端,定位到js脚本文件所在目录,输入
node 文件名.js
执行对应的文件;文件名不可以使用node.js;
Node读文件操作
—浏览器中的JavaScript是没有文件操作的能力的,但是node中JS具有文件操作能力;
—在Node中如果想要进行文件操作,就必须引入fs(filesystem)这个核心模块;fs核心模块提供了所有的文件操作相关的API;
【1】在js脚本文件中,加载fs核心模块:
var fs = require('fs')
【2】读取文件:
fs.readFile(文件路径,function(error,data){})
;传递第一个参数为读取文件的路径,第二个参数为回调函数,回调函数中传入两个参数error和data,读取失败error就是错误对象,data是undefined
,读取成功data是读取到的数据,而error是null
;【2】文件中存储的是二进制数据,我们在读取的时候看到的是16进制(二进制转换为16进制),因此可以在回调函数中将读取数据转为字符形式:
data.toString()
Node写文件操作
—写入文件API:
fs.writeFile(文件路径,文件内容,err => {})
—第一个参数为写入文件的路径,第二个参数为写入文件的内容,第三个参数为回调函数,传递错误信息;
—我们在进行读取文件时,可以首先判断是否有错误:
if(err){ console.log(err) //终止读写操作 return }
Node简单http服务
—HTTP核心模块是Node.js网络的关键模块,它可以帮助编写创建服务器!
【1】加载http核心模块:
const http = require('http')
【2】通过
http.createServer()
,其返回http.Server
类的实例,创建web服务器:var server = http.createServer()
【3】当客户端请求过来自动触发服务器的request请求事件,然后执行第二个参数:请求事件处理回调函数,传递两个参数,第一个参数为Request请求对象,可以获取客户端的一些请求信息,例如请求路径;Response响应对象,可以给客户端发送响应信息;
server.on('request',fucntion(request,response){ console.log('收到了客户端的请求,请求路径:'+request.url) })【4】绑定端口号,启动服务器,第一个参数为端口号,第二个参数为回调函数,启动成功后回调函数:
server.listen(3000,function(){})
【5】关闭创建的服务器进程:Ctrl+C
【6】返回客户端响应,response对象存在一个方法
write
可以用来给客户端发送响应数据:server.on('request',function(request,response){ //write方法可以调用多次,但是必须使用end来结束响应,否则客户端一直等待 response.write('hello') //告诉客户端,话说完,可以呈递给用户了 response.end() //但是上面的响应方式较为繁琐,可以直接响应数据并结束会话 response.end('hello') })
请求不同路径响应不同页面
—根据客户端不同的请求url返回不同的响应,一个url其实对应的是一个资源:
server.on('request',function(req,res){ //根据不同请求路径发送不同响应的结果 //1. 获取请求路径,获取的是端口号之后的路径内容,并且所有请求路径都是以/开头的 var url = req.url //2. 判断url,返回不同响应页面 if(url === '/'){ res.end('index page') }else if(url === '/login'){ res.end('login page') }else{ res.end('404 Not Found') } })—2注意响应内容只能是二进制数据Buffer或者字符串String,因此需要通过
JSON.stringfy(products)
将数据转换为字符串形式;
Node模块系统
—Node中模块有三种:具名核心模块、用户自定义编写模块和,都是通过
require
进行模块加载;—在用户自编写的模块下,相对路径必须加上
./
表示加载当前文件夹的模块,并且在加载过程可以省略.js后缀名;—Node中没有全局作用域,只有模块作用域(文件作用域),外部访问不到内部,内部也访问不到外部,当前文件访问不到加载模块下的相关变量和函数等,而加载模块同样也访问不到当前文件下的变量和函数等;
—模块作用域之间如何进行通信,简单模块化的加载与导出:
【1】
require
方法可以实现加载文件模块并执行模块代码,可以实现加载执行多个JavaScript脚本文件;另外还可以拿到被加载文件模块导出的接口对象【2】
require
加载只能是执行其中的代码,文件与文件之间由于是模块作用域,不会有污染问题,模块完全是封闭的;这样可以避免变量命名冲突污染的问题【3】每个文件模块中都提供一个对象
exports
,默认是一个空对象;我们可以将所有需要被外部访问的成员挂载到exports
接口对象,这样就可以访问被加载模块的相关接口;
Content-Type
—在http协议中,Content-Type就是用来告知对方我给你发送的数据内容是什么类型,根据不同类型进行内容识别;
—可以访问https://tool.oschina.net/进行相关文本格式的查询,不同资源对应的不同文本格式Content-Type;
—在服务端默认发送的数据,其实是utf8编码内容,但是浏览器并不会识别utf8编码的内容,在它不知道服务器响应内容的编码情况下,会按照当前操作系统的默认编码去解析;中文操作系统默认编码是GBK;因此服务器最好把每次响应的数据是什么内容类型告诉客户端;
—因此我们需要在返回响应时,告知浏览器响应内容的编码方式:
res.setHeader('Content-Type','text/plain;charset=utf-8')
—图片不需要指定编码,一般只为字符数据才指定编码格式;
—
setHeader
函数设置HTTP消息头的值,不同的资源对应的Content-Type是不同的,其中传递的第二个参数为文本格式,其中text/plain
为普通文本格式,text/html
为HTML文本格式,浏览器会对html文本进行解析;—一般我们在向服务器发送请求的时候,服务器响应给我们的是页面的文本内容,我们可以结合fs核心模块将响应页面通过文件读取的操作返回给客户端:
fs.readFile('./resource/index.html',function(err,data){ if(err){ //设置HTTP消息头的相关格式 res.setHeader('Content-Type','text/plain;charset=utf-8') res.end('文件读取失败,请稍后再试') }else{ //读取文件内容,这里文本格式是html文本 //另外需要注意,图片不需要编码,我们常说的编码一般指的是字符编码 res.setHeader('Content-Type','text/html;charset=utf-8') res.end(data) } })—另外,除了Content-Type可以用来指定编码,也可以在HTML页面通过
meta
元数据来声明当前文本的编码格式,浏览器会识别它;
IP地址和端口号
—所有联网的程序都需要进行网络通信,计算机中只有一个物理网卡,而且同一个局域网中,网卡的地址必须是唯一的;网卡是通过唯一的IP地址来进行定位的;
—IP地址用来定位计算机,而端口号是用来定位具体的应用程序(比如QQ、微信、Apache服务器等,所有需要联网通信的软件都必须具有端口号);
—端口号范围为0~65536之间,在计算机中有一些默认端口号,最好不要去使用,比如http服务的80;在开发过程中不要使用特殊的端口号,一般使用像3000、5000等没有特殊含义的端口号;
—可以同时开启多个服务,但一定要确保不同的服务占用的端口号不一致;简单来说,在一台计算机上,同一端口号同一时间只能被一个程序占用;