NodeJS入门——学习笔记

之前有段时间闲着无聊,去B站上简单了解了一下NodeJS,下面是根据一个视频记录的笔记,供大家参考,错误之处请大家帮忙斧正。侵删。

目录

0 参考教程

1 NodeJs简介

1.1 官网介绍:https://nodejs.org/en/

1.2 安装NodeJs

1.3 NodeJS哲学

2 开发服务器程序

2.1 helloworld 02.js

2.2 NodeJS是运行在服务器端

2.3 NodeJS架构

3 Node.JS特定

3.1 单线程

3.2 异步I/O

3.3 事件驱动

4 路由机制

4.1 路由表

4.2 静态资源的文件使用 08.js

4.3 路由机制 - url模块,path模块,querystring ——09.js

4.4 路由机制  小程序:——小小阿帕奇(静态资源文件)  10.js

5 小结

6 模块

6.1 内置模块

6.2 自定义模块

6.2.1 require谁,就运行谁

6.2.2 require的模块中能够,如果有异步函数,将不会等待

6.2.3 连续require

6.2.4 循环引用

6.2.5 文件夹的层次

6.3 JS文件天生是隔离作用域的

6.4 使用exports.xx = xx 暴露属性出去

6.5 使用module.exports暴露

6.6 神奇的node_modules文件夹

7 npm的世界

7.1 npm使用

7.2 依赖

7.3 全局安装

7.4 淘宝镜像

8 GET请求和POST请求

8.1 GET请求

8.2 POST请求

8.3 formidable模块

9 Express框架入门

9.1 基本使用

9.2 静态路由

9.3 使用某一个页面

9.4 模板引擎


0 参考教程

教程http://www.runoob.com/nodejs/nodejs-tutorial.html

公开课教程https://www.bilibili.com/video/av26470001?p=4  18h

教程https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Express_Nodejs

1 NodeJs简介

1.1 官网介绍https://nodejs.org/en/

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

Node.js是一个构建在chrome's V8 JS引擎上的一个JavaScript的运行环境

Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.

Node.js使用了事件驱动,非阻塞I/O模型,是轻量级的和高效的

Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

Node.js的包生态(npm),是世界上最大的开源库生态系统

1.2 安装NodeJs

Node.js可以在任何操作系统上安装,底层是chrome V8引擎。

下载地址https://nodejs.org/en/

安装方法:下载run安装就可以

如何证明是否安装好了呢?

  • 进入terminal
  • $node -v //查看安装的版本号

为什么能够输入node命令呢

  • 在/usr/local/bin下面有node可执行程序

此时拥有了两个运行环境 :一个node,一个浏览器。若用浏览器解析,需要在h5文件中引用js文件,才能解析。

此时,证明了nodejs是一个JavaScript runtime(js运行环境)。

 

Node.js特点单线程,非阻塞异步I/O,事件驱动

Node.js使JS的触角延伸到了服务器开发中,在node的世界中,我们关心的不再是JS操作网页上的DOM,制作交互动画,表单验证……而是服务器端的事情:HTTP请求的处理,GET请求,和POST请求,数据库增删改查,cookie和session等等。

1.3 NodeJS哲学

这是一个帅哥为了解决性能问题而发明了Node JS

异步I/O:绝大多数网站I/O是非常多的,I是数据的读取Input,O是数据的输出Output。但是在读取I/O时,CPU就被闲置了。

2008年Google发明了Chrome V8满足它关于高性能web服务器的想象,使用V8引擎解析JS程序,非常的快,并且V8隐性性能好,都是异步I/O,闭包特性方便,Ryan Dah1就把V8移植到服务器端。

2 开发服务器程序

2.1 helloworld 02.js

2.2 NodeJS是运行在服务器端

注意,此时查看源代码,在页面上查看不到(3+4),而是7,说明js运行了在服务器上,而不是前端的js。

Nodejs程序在服务器端运行。

2.3 NodeJS架构

NodeJS是一个让JS运行在服务器端的开发平台,它让JS的触角伸到了服务器端,但是Node似乎和其他服务器有点不同,如:PHP,ASP,JSP:

  • Node.js不是一个独立的语言,与PHP,Perl,python,jsp,ruby的“既是语言,也是平台”不同,Node.JS使用JS进行编程。NodeJS是一个工具,语言仍是JS。
  • 与PHP,JSP不同,Nodejs跳过来Apache,Tomcat,Nginx,IIS等HTTP服务器。它自己不用健在任何服务器软件上,NodeJs的许多设计理念与经典架构LAMP有着很大不同,可以提供强大的伸缩能力
  • Nodejs自身哲学:花最小的硬件成本,追求更高的并发和处理性能

我们使用NodeJS开发服务器:GET请求,POST请求,POST请求参数的处理,数据库的增删改查,Cookie,session等等。

NodeJS没有根目录的概念!!!

3 Node.JS特定

3.1 单线程

在Java,PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的进程,而每个进程需要耗费大约2MB内存,也就是说,理论上一个8GB内存的服务器可以同时连接的最大用户数为4000个左右,要让web应用程序同时支持更多的用户,就需要增加服务器的数量,而web英语程序的硬件成本当然就上升了。

Node.js不为每个客户连接创建一个新的线程,而是使用一个线程。当有用户连接,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用NodeJS,一个8GB内存的服务器可以同时处理超过4W用户的链接。

另外,单线程带来的好处还有:OS不需要再有线程创建、销毁的时间开销。

证明1:nodejs是单线程的  03.js

 

我们发现,所有用户共享了同一个变量a。

证明2:nodejs是单线程的 04.js

写了一个小程序,如果因为程序有错误,此时唯一的node进程将停止,此时会导致所有访问者无法访问

 

3.2 异步I/O

异步I/O:一个服务员,照顾很多客人。

 

当一个访问者访问服务器后,此时这个人就会去读取文本文件,此时CPU并没有被阻塞,其他人仍旧可以访问。当这个人的文本文件读取完毕之后,此时就会使用回调函数呈现页面。

只要I/O越多,NodeJS宏观上越并行。

NodeJS适合开发I/O多的任务,但不适合计算繁多的任务!

 

下图:

左图:多线程的宏观并行,CPU经常会等待I/O结束,CPU的性能会白白浪费;右图:单线程的宏观并行,单线程的程序,当并行极大的时候,CPU理论上的计算能力是100%。

 

 

因为Nodejs想在破的机器上也能够运行,所以剑走偏锋采用了单线程的模式,既然单线程必须异步I/O。

例如:挡在访问数据库取得的数据的时候,需要一段时间。在传统的处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库的返回结果,才能执行后面的代码,即:I/O阻塞了代码的执行,极大地降低了程序的执行效率。

由于Nodejs中采用非阻塞I/O,因此在执行力访问数据库的代码后,将立即转而执行其后面的代码,把数据库返回的结果放在回调函数中,从而提高了程序的执行效率。

当某个I/O执行完毕后,将以事件的形式通知执行I/O操作的线程,线程执行这个事件的回调函数,为了处理异步I/O,线程必须有事件循环,不断地检查有没有未处理的时间,依次予以处理。

3.3 事件驱动

事件驱动是Nodejs的底层机制,我们只需要了解Nodejs不会上错菜的原因就是事件驱动,有一个事件环。

 

事件环机制是Nodejs的底层机制,保证了Nodejs可以高效准确的运行,而不会紊乱。

4 路由机制

4.1 路由表

这是重点和难点

之前的案例,不管访问3000端口的什么网址,都能得到同样的结果。如果要根据用户访问的网址,给用户不同的显示,就需要使用req的url属性来进行判断。

此时,就知道了req里面是用户访问的请求信息,请求的网址是req,res是服务器的响应信息。

事实上,我们并不存在music文件夹、news文件夹,甚至我们可以伪装一个地址,但实际上并不存在music.html文件。

 

更加证明了Node.js是没有Apache的,是没有URL和真实物理文件映射关系的,这叫做顶层路由设计。能够支持顶层路由设计的比较流行的语言只有Node.js和Python。

 

甚至可以用正则表达式验证url是否匹配某一个模式,恶补正则:

补充:

js中正则:exec(): 最好用的;search();replace();test()

 

结合fs模块,做了一个小小的学生管理系统,顶层路由可以设计的非常漂亮,比如:

http://127.0.0.1:3000/student/100001

就是检索100001号的学生的情况,比如:

http://127.0.0.1:3000/student.php?xuehao=100003

不知道高明到哪里去了,后面将知道,这种风格的路由叫做RESTful类型的路由。

至此,顶级路由案例学完了07.js。

Noticed: res.end("")表示结束输出流,让网页停止转动。

4.2 静态资源的文件使用 08.js

我们现在不要进入Apaxhe的世界中无法自拔,Apache是一个怎样的世界:是一个物理文件和URL --对应的世界,比如:

但是,Nodejs没有根目录的概念!没有URL和物理文件一一对应的关系!

此时,如果我们的Html页面上,试图插入一个图片。

此时,才能往页面中插入图片。

我们要做一个静态资源管理器,但是需要储备知识,接下来介绍URL模块和path模块。

4.3 路由机制 - url模块,path模块,querystring ——09.js

如果一个URL比较完整,包括querystring部分(就是GET请求查询字符串传参部分),hash部分,那么此时

http://127.0.0.1:3000/b.html?id=123#123

req.url是:/b.html?id=123

即:querystring属于req.url,但是hash不属于。

但是,我们此时要得到文件名的部分,我不想要querystring,此时可以用正则提炼,但是太麻烦。

Node中提供了内置模块,url,path,querystring模块,都可以服务于url识别。

代码09.js:

网址是:

http://127.0.0.1:3000/haha/1.html?id=123&name=小明#abc

输出:

没有正确识别protocal协议,host主机名等等,但是能够正确识别pathname,query,

如果加上url.parse(req.url, true),此时querystring部分将会自动变为一个对象,方便我们存入到数据库中。

还有两个模块,path和querystring模块,都是服务于url提取的。

示意图:

他们还有其他方法,也暂时不用预习,后面项目会用的而别凶。

4.4 路由机制  小程序——小小阿帕奇(静态资源文件)  10.js

创建一个文件夹myweb,我们的程序能够自动为文件里面呢的文件,图片,css,js加上路由

基本结构好思想:用户输入什么URL,我就真的用fs去读那个文件:

有几个不好用的地方:

第一点:首先是content-type的是。

就是说如果我们访问的是.html文件,那么content-type="text/html",如果是image,那么应该是"mime/jpeg".

解决方案:

第二点:不能自动识别首页:.index文件

比如我们输入127.0.0.1:3000/b,希望读取myweb中b文件夹里面的index.html

解决方案:这种路径都没有拓展名,如果用户输入了一个url都没有拓展名,则自动那个不全一个index.html即可。

第三点还有一个更大的问题,就是304的问题,304状态码not mofified, 当文件没有改变的时候,服务器要发出304状态码,拒绝传输文件;我们的小程序没有这样的识别,我们也不解决了,因为确实太复杂,还要利用session和cookie保存镜像。

5 小结

Q1: Nodejs是什么

是一个JS的runtime,运行环境。实际上就是利用chrom v8引擎,将它一直到了服务器上,用它去开发服务器程序,可以提供HTTP服务。

Q2:Nodejs的主要特点?

A:Single-thread; non-blocking IO; Event driven事件驱动。

这三个特点是相辅相成的,是必须的选择。

Nodejs为了在低硬件服务器条件下高并发,所以就要减少内存消耗,所以剑走偏锋,选择了单线程,因此必须使用非阻塞I/O,因为只有一个线程,就必须当A用户去I/O时,处理B的业务的事情;B业务去I/O时,处理C的事情。。。。A、B、C都有回调函数。

为了让A、B、C都不乱套,每个人都进行合理调度,谁先来,处理谁,不能让B一直等待,处理C、D、E。。。。所以Node使用事件环,采用事件驱动来调度事件。

Q3 下列那条语句是正确的,为什么?

A: var data = fs.readFile("./test.txt"); 错误

B: fs.readFile("./test.txt", function(err,data){…});  正确

因为fs.readFile是异步方法,事实上Node的fs模块,mongdb模块基本上都是异步方法。一定要记住,异步函数不能通过return返回,不能通过等号来接受数据。必须通过回调函数传实参的模式来传输数据。

Q4 说说http模块,它有哪些功能,有哪些方法?req和res各有什么属性和方法?

A:http模块用来提供http服务的,最常用的就是http.createServer((req,res)=>{}); 创建一个服务器。

req封装了HTTP上行请求的所有信息,常用属性req.url, req.connection.remoteAddress、 req.type等等。

Res是服务器应该给出的下行响应,常用方法是res.write(), res.write(), res.setHeder()…

Q5 说说nodejs的顶层路由设计

Apache和Nodejs的模式完全不一样。

Apache天生有静态资源服务,但是nodejs不行,nodejs必须使用路由清单给出明确的路由才行。

Q6 说说常用的cmd命令

cmd命令在windows下很弱,将来我们学习linux你会发现相当强大。

$clear - 清除屏幕内容

$cd - 切换文件夹

$ls- 列出当前文件夹下的所有文件

$node - 执行node.js文件

$ctrl+C - 打断进程

6 模块

模块module,指的是一些列有关系的js程序的集合

后面我们学习的MVC: model,view,control。

6.1 内置模块

Nodejs中内置了很多模块,可以直接用require进行引用,按照国际惯例来讲,你接受的名字最好和模块一样。

内置模块的引用使用require函数,引用是无路径的、无条件的。在任何目录下,都是通过require("http")来引用内置http模块的,而不需要require("../http")

内置模块是nodejs天生就有的。nodejs手册:http://nodejs.cn/api/

后面还会学习一些模块,注意记忆里面常用的方法和属性,比如:

url.parse()

querystring.parse()

6.2 自定义模块

每一个js文件就是一个模块,Node.js使用CMD(通用模块定义规范)。后面我们将知道webpack、seajs也使用哪个的是cmd规范,而Angular,requirejs等使用的是amd(异步模块定义)规范。

接下来了解Node.js模块的一些特性,而这些特性今后在学习webpack,seajs的时候也是通用的。

6.2.1 require谁,就运行谁

结论:require谁,就会运行谁。

注意:require("./test.js")中的。./坚决不能省略。因为如果省略了,代表读取node_module文件夹中的文件

6.2.2 require的模块中能够,如果有异步函数,将不会等待

结论:require文件中,如果有异步语句,此时nodejs仍然不会死等它结束,会返回执行文件中的程序,如果文件读取完毕,执行回调函数。

6.2.3 连续require

6.2.4 循环引用

如果A引用B,B又引用了A,会发生什么呢?

答案NodeJS很智能,如果B重新引用了A,此时如同没有引用一样,会帮你自动抑制。

6.2.5 文件夹的层次

 

 

 

6.3 JS文件天生是隔离作用域的

结论:在Node.js中,每个js文件是一个单独的作用域。和DOM浏览器开发不一样,浏览器中, var a 此时a自动成为了window对象的属性,此时js文件和js文件可以共享作用域。 但是nodejs中,每个js文件是个铜墙铁壁,天生是隔离作用域的。

6.4 使用exports.xx = xx 暴露属性出去

 

 

我们如果想要把元素、变量、函数向外暴露 ,此时可以使用exports.** = **向外暴露,

此时引用这个模块的文件将用等号来接受,等号左边的变量将自动成为exports对象。

上面的例子中,var test 这个变量就是exports对象。

 

这种暴露非常好用,通常用于类似的功能向外暴露。比如mathtool.js:

mathtool.js

01.js

6.5 使用module.exports暴露

刚刚我们一个js文件中向外暴露了多个东西,比如sum, average,pingfang等等。但是如果一个js文件中,仅仅向外暴露一个东西,此时用module.exports不方便。比如我们要向外暴露一个类。

结构:

调用函数的时候,要使用People.People()写法,非常不方便。

原因是什么?因为js文件中要暴露很多东西。

此时,Nodejs建议使用module.exports= People.

6.6 神奇的node_modules文件夹

如果我们写一个引用,没有写./:

此时表示引用node_modules文件夹中的文件。

并且更为神奇的是,node_modules文件夹里面的模块,在引用的时候不需要考虑路径,只需要确保node_modules文件夹需要引用的模块的js文件里路径的任何祖先路径中。

 

不仅如此,比如我们haha.js文件,它不是要引入test.js吗,只要node_modules文件夹出现在任何haha.js的祖先目录中都可以

但是,其他的非祖先文件夹不行!!!

但是有一个路径更神奇,叫做系统环境路径,在:

C:\Users\你的电脑名字\AppData\Roaming\npm\node_modules

天下无人不识君,这个是全局路径。

当省略文件名的时候,会自动识别index.js文件

 

 

做对这个题目,就说明已经会了

Q: 下列的四种require写法,实际引入的是谁?

Require("./a.js")  -- 引入当前文件夹中的a.js

Require("a.js") -- 引入node_modules中的a.js文件

Require("a") --引入的是node_modules文件夹中的a文件夹的index.js文件

Require("./a") --引入的是当前文件夹中的a文件夹中的index.js文件。

7 npm的世界

我们刚刚封装了一个数学函数mathtool很好用,此时node开发中也发现了这个事情,如果让全球开发者贡献自己的实用模块那该多好。让大家不要重复造轮子。

说一下什么是模块,一个math-tool就是一个模块。但是如果5、6个js文件都是服务于数学方面的,那它们的整体又可以作为一个大模块。例如:

Math-tool整体就是一个大函数。

所以Nodejs主导了一个社区,叫做npm(node package management, node包管理器)。

7.1 npm使用

网址https://www.npmjs.com/

淘宝镜像 https://npm.taobao.org/

此时就可以在上面寻找我们要的东西,比如现在有需求,比如:把公历变为农历。第一时间就要想到,我不要重复造轮子,要去npm社区找找看!

搜索“农历”就可以,点击详情,就可以看到api

直接使用npm命令就可以下载,npm是随着node安装的,

$npm install solarlunar

注意:一定要联网。此时solarlunar这个模块就会被自动的下载到你项目的node_modules文件夹。

非常神奇!此时通过查看API,可以实现我们的业务了。

7.2 依赖

很明显,现在的项目03.js依赖了两个别人的包,分别是:chinese-finance-number,solarLunar。显然的,node_modules是不能删除的,否则一定会报错。

但是我们现在用U盘拷贝项目给别人,此时完全没有必要去拷贝node_modules文件夹,因为这里面的东西在npm线上啊,npm很稳定,随时可以下载!

npm有一个创造性的举动,可以让开发者声明自己的项目的全部依赖,可以告诉别人该项目依赖什么文件。

创建package.json中,定义项目依赖的包,如下:

将package.json放入到项目的根目录中,再

$ npm install命令就可以自动安装项目需要的包

所以package.json文件非常重要,就是项目的身份证!事实上,里面还有很多配置项。

可以用:

$npm init

此时npm将会有一个表单,引导你去创建一个较为完整的package.json文件。此时,只需要回答一些问题即可,如果默认选项则按回车即可。会帮我们生成:如下。

版本符号:

我们看看npm的手册: https://docs.npmjs.com/files/package.json

常用举例:

但是还是不方便,如果我们安装一个以来的时候,能够自动进入到package.json中,就好了!

$npm install solarlunar --save

可以帮助我们自动将依赖项solarlunar加入到package.json中。

如果想要限制版本

$npm install solarlunar#^1.0.0 --save

卸载

$npm uninstall **

总结

$npm init //帮我们创建一个package.json文件的,项目开发的第一件事就是这个。

$npm install //根据package.json文件,安装全部的项目依赖

$npm install solarlunar //install solarlunar package

$npm install solarlunar -- save// install package and write dependencies into package.json.

7.3 全局安装

$npm install package_name -g 

此时,这个包会被安全到全局。

Mac下地址: /usr/local/lib/node_modules

可以通过$npm list -g查看所有全局安装的模块。

一些CLI(命令行程序)、工程化的东西将被安装到全局。随着学习的深入,我们将遇见。

7.4 淘宝镜像

淘宝为了方便中国程序员对抗GFW,就提供了淘宝镜像cnpm。你可以用此代替官方版本(只读),同步频率目前5分钟一次,以保证与官网同步。

如何设置淘宝镜像呢?如下:

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

今后所有的npm活动操作只要用cnpm代替即可。

最后说一句,有很多包非常大,自己也依赖别人,不用怕,他们的依赖也写在了他们自己的package.json文件中。

cnpm,npm可以深入读取每个包的package.json, 能够自动将其依赖都下载下来。

npm是个怎样的世界?就是站在巨人的肩膀上,而他也站在别人的肩膀上。。。。

8 GET请求和POST请求

8.1 GET请求

Get 请求传参数通过URL,POST请求传参通过HTTP上行报文。GET请求不安全,方便分享网址;POST请求安全,不方便分享往回,内容信息无限长。

GET请求的参数在URL中:

Nodejs如果获得get请求,实际上就是如何解析URL,昨天已经讲过了。就是:

安装一个小型服务器,因为只有服务器环境才能发出Ajax请求。

$ cnpm install serve-static --save

$ cnpm install finalhandler --save

8.2 POST请求

8.3 formidable模块

npm上可以下载一个formidable的模块,用来处理post请求。甚至可以处理图片、zip等多媒体文件的上传。

APi文档: https://npm.taobao.org/package/formidable

Step1 - install dependency

$cnpm install --save formidable

Step2 - 通过看API来学习和使用

9 Express框架入门

传统Node.js的缺点:

 - 路由不方便制作,尤其是正则表达式路由

- 静态资源服务不方便

- 页面呈递不方便,没有模板引擎

官网:https://expressjs.com/zh-cn/

 

Express 高度包容、快速而极简的 Node.js Web 框架。 是一种保持最低程度规模的灵活 Node.js Web 应用程序框架,为 Web 和移动应用程序提供一组强大的功能。

Express 提供精简的基本 Web 应用程序功能,而不会隐藏您了解和青睐的 Node.js 功能。

基于Express的流行框架

 

9.1 基本使用

$cnpm install express --save

然后就可以写基本的demo了,基本上都是固定动作,没什么好解释的

看一下中间件的特写:

表示当用get请求访问/news时做的事情,此时输出使用res.send()而不是res.end().好处是自动变成UTF-8编码。

并且express是自动使用pathname与/news进行比较,就是说会自动过滤querystring,hash等等。

我们可以用冒号:来引导一个变量,此时特别方便做一个正则的路由:

 

9.2 静态路由

一个中间件解决问题:

App.use("/jingtai", express.static("public"));

use表示使用中间件,刚才的get表示在get请求下使用中间件。use是无论什么请求都会使用。

此时我们放置在public文件夹中的xx.png会被路由到/jingtai下:

http://127.0.0.1:3000/jingtai/xx.png

静态资源表放在最后,省得拦截别的!

9.3 使用某一个页面

例如:当我们访问/的时候,我们就想要呈递一个public/haha.html页面,这是一个经常的事情

此时不需要那个逻辑了:

而是:
 

//express的常用的send函数

res.sendFile(页面绝对路径)//发送页面给用户

res.send(content)//发送内容给用户

9.4 模板引擎

express可以像php一样使用模板引擎,此时最好用的模板引擎就是ejs

全称:Embedded JavaScript templates 嵌入式JS模板

API: https://npm.taobao.org/package/ejs

$cnpm install ejs --save

使用案例1:

发生了什么?

此时当用户访问/的时候,会自动使用views文件夹中的shouye.ejs当做模板。字典就是后面传入的json。

模板是后台服务器填充的,访问者休想看到源代码。

 

使用案例2:

views/shouye.ejs

输出效果:

很方便,任何JS中能够使用的数据类型都能传:

08.js

views/shouye.ejs

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值