注意:前置知识:回调函数,异步,ajax技术,端口
目录
1.什么是node.js
写后端如烹小鲜,而我,不会做饭
一般来说,我们很少用javascript去构建一个后端应用,而是把js划分到经典前端三剑客之一(话说前两天看到一个大哥用js在前端写出了云端图片处理软件........牛蛙牛蛙).把JS解释为机器代码的引擎,其实就是浏览器的底层机制.
而Node.js不是一个编程语言或者框架,而是一个环境,能够脱离浏览器构建一个能让js跑起来的环境.简单来说,就是用js写后端
如果想要区分当前运行环境是浏览器还是node.js,可以了解一下原型prototype,其中浏览器的顶层应该是window,而node.js的底层却是global.
下面不会特别区分nodejs的语法,只会展示一些有关的操作,因为很多其实都是es6的内容这个东西也没有必要特意去学)
其实这篇也近乎解释了为什么vue这类框架需要提前安装node.js
node.js的安装可以直接进入官网Node.js (nodejs.org)
建议选择支持比较多的版本,较为稳定
并且在下载之后要手动配置环境变量,和你们配置java是一样的
2.模块的概念
模块仍然是es系列标准之一,在这里,每个javascript文件我们都可以将其视为一个模块,或者一个模块的生产者,一个文件可以选择自己想要抛出哪些东西,形成一个其他文件可以require的对象
举个例子
我们有一个名为app2.js的文件,里面要抛出两个东西,变量a和函数counter
把这两个东西以一个对象的形式抛出,就可以在其他的模块中读取到
在其他的文件中,以对象的形式进行引入,就可以调用这个模块内的属性,函数之类的东西
很类似java中的导包,cpp中的头文件
模块化开发是一个非常重要的思想,后面常用的模块包括文件管理fs,路由管理url,服务器网络管理http协议,都是内置的模块,可以直接使用require语句调用
3. 回调函数
在大多数异步方法中,回调函数可以作为异步处理的一个机制,比如某个函数内置了一个回调函数的参数,就可以设置这个回调函数,来进行异步完成操作以后的行为
关于具体的回调函数的内容,可以详见前面关于异步操作的解释
回调函数是异步操作的一部分,当异步操作完成后会触发回调函数的执行。
在 Node.js 中,回调函数的参数名称并没有限制,通常根据异步操作的结果类型和具体含义来命名参数。一般来说第一个是错误类型,实际由母函数的情况决定
4.关于文件的管理
文件关系的模块为fs,流相关的东西也在这里
var fs=require("fs");
文件的管理分为两种,异步和同步,主要的操作其实也就四个,读入,读出,创建文件夹,删除文件夹
(1)同步操作
同步完成文本文件的读入和读出
用一个变量进行接收,接收的时候要注意编码
var readme=fs.readFileSync("./readme","utf-8");
然后向指定位置写出
fs.writeFileSync("./writeme",readme);
同步完成文件夹的赋值和删除省略
(2)异步操作,区别就在于会异步执行回调函数
所以比如读出的回调函数中,可以启动写入,让逻辑更加清晰
这个回调函数会在执行完流创建以后进行读取
var readme2=fs.readFile("./readme","utf-8",()=>{
fs.writeFile("./writeme",readme+",and you are finished too!",()=>{
console.log("you are finished");
});
});
异步进行文件加创建
fs.mkdir("stuff",()=>{
console.log("创建成功");
});
fs.rmdir("stuff",()=>{
console.log("删除成功")
});
5.关于流的操作
流其实和java里面是差不多的东西,也是一种文件处理机制,不过比Java简单太多了
此外,在nodejs构成的服务器端,request和response也具有流的性质
流其实也是eventEmitter的一个实例,所以也具有监听事件的方法on
(对于写入流,有两个事件,data和end,其中data是每一部分文件传入结束时触发的,传入回调函数的参数就是这一部分数据.而end事件是整体的数据传入完成以后才会触发的,data事件会触发多次,但是end事件只会触发一次)
另外注意:当一个可读流(Readable stream)被监听了 data
事件时,数据就开始流动,每当数据块(chunk)被读取时,Readable stream 就会触发 data
事件,将数据块传递给相应的事件处理函数。因此,通过监听 data
事件,我们可以实时获取数据流中的数据。
var readStream=fs.createReadStream("./readme","utf-8");
var writeSeam=fs.createWriteStream("./writeme","utf-8");
readStream.on("data",(data)=>{
writeSeam.write(data,()=>{
console.log("一部分数据传递成功");
});
})
data会多次执行
readStream.on("end",()=>{
console.log("数据全部传递成功");//这是个异步方法
})
end只会执行一次
解释游戏啊这段代码,这两个流分别根据写入和写出方向构建了两个对象,每次readStream读到了一定数目的数据,就触发data事件,我们根据这个回调函数完成写入流的操作
6.关于构建服务器:前端部分,如何向后端发送请求
发送请求一共是两种:get请求,这种请求主要用来从后端获取大量数据,也可以通过url的方式向后端传递几个简单的参数
这里发送请求的方式是使用ajax技术,可以详见我之前写过的关于ajax的基本使用介绍
[前端基础]关于AJAX的一些梳理_术鸦的博客-CSDN博客
var xhp=new XMLHttpRequest;
xhp.open(GET,"http://localhost:3030");
xhp.onreadystatechange=(()=>{
........................
});
xhp.send();
post请求:主要用于往后端传入大量数据,区别就在于open函数中的第一个参数改成POST
var xhp=new XMLHttpRequest;
xhp.open(method,"http://localhost:3030"); //区别1,这里改成post
xhp.onreadystatechange=(()=>{
..................................
});
xhp.send("post发送请求的内容"); //区别2,可以传入数据
7.后端创建简单的服务器对象
服务器有关的东西在模块http中,先引入这个模块,这个模块管理的是http协议下的东西哦,包括构建
var http=require("http");
然后利用http模块中的createServer函数,创建一个服务器,这个函数中内嵌着一个回调函数作为参数使用,这个参数带有两个参数,就是请求体对象req和回复体对象res
在这里再谈报文格式显然有点超出格式了,所以我们只说需要干些什么
设置返回状态码,设置返回报文头,以及返回体,这里解释一下为什么前后端可以传递信息,因为在http协议下,传递信息的格式被限制成了"报文"
报文的具体格式可以查阅相关文档
req对象是前端发送过来的,本质上是一个流对象,我们可以直接监听data事件,可以自动开始读取
var http=require("http");
var server=http.createServer((req, res)=>{
res.statusCode=200; //设置状态码
res.setHeader('Access-Control-Allow-Origin', '*'); //设置头
if(req.method==='POST'){ //根据请求的方式确定如何处理数据
//传回来的大量数据使用流的方式进行处理
req.on("data",(data)=>{
console.log(data);
});
req.on("end",()=>{
console.log("已经完成请求了");
});
res.end("来自后端,经过POST请求的数据");
}else{
res.end("来自后端,经过GET请求的大量数据");
}
})
最后监听端口,
端口就相当于这个服务器对象对外开放的窗口,前端需要从端口访问这个进程,才能有结果
server.listen("3030","127.0.0.1",()=>{
console.log("服务器开始监视3030端口")
});
8.后端如何处理请求
(1)如果是post请求,我们主要需要把req中带来的数据给读取即可
建议使用流的方式读取,刻度流
req.on("data",(data)=>{
console.log(data);
});
req.on("end",()=>{
console.log("已经完成请求了");
});
(2)如果是get请求,我们需要往前端传入数据
按照目前来说,使用end函数进行返回,是最简单的方式
res.end("来自后端,经过GET请求的大量数据");
9.前端如何处理返回的数据
前端处理返回数据的方式目前只学习了简单数据,太大的数据需要改变为流对象
这个后面有缘再说吧QWQ
xmlhttprequest对象中,有一个response对象,这个东西就算返回的数据
读取示例
console.log(xhp.response);
10.简易应答和访问的实现代码
var http=require("http");
var server=http.createServer((req, res)=>{
res.statusCode=200; //设置状态码
res.setHeader('Access-Control-Allow-Origin', '*'); //设置头
if(req.method==='POST'){ //根据请求的方式确定如何处理数据
res.end("来自后端,经过POST请求的数据");
}else{
res.end("来自后端,经过GET请求的大量数据");
}
})
server.listen("3030","127.0.0.1",()=>{
console.log("服务器开始监视3030端口")
});
前端代码如下
function detchData(method){
var xhp=new XMLHttpRequest;
xhp.open(method,"http://localhost:3030");
xhp.onreadystatechange=(()=>{
if(xhp.readyState===4 && xhp.status===200){
//这里根据不同的情况返回不同的数值
console.log(xhp.response);
}
});
xhp.send("post发送请求的内容");
}
11.关于node.js的其他补充
(1)NPM包管理机制
npm可以理解为一个开源的社区?其实是nodejs的模块包管理,通过npm的方式可以获得别人弄好的轮子(比如常用的express.js,可以大大简化操作)
或者可以理解为一个共享机制?可以用来下载别人的包
npm是node.js自带的一个命令
(2)介绍另一个启动方式
nodemon,一个工具,检测文件改变,然后会重启后端
使用npm的方式进行安装
启动项目的方式也从node变成了nodemon
这个东西也可以到时候写到脚本里面
(3)package.json
这个东西可以说是老朋友了,就目前我们接触到的来说,有两种用法
1.记录着我们在项目中的依赖,启用指令
npm install
就可以读取记录信息,可以把用到的模块重新下载
这种是方便接收其他人的项目
2.这个文件中内置着某些启动脚本,idea启动也是根据这个json文件中的脚本来进行的
比如我们想要改成nodemon方式启动项目,就可以在这个文件里修改