Nodejs使用教程、及其常用内置模块!web服务器立即创建!

文章目录

  • 前言
    • 前端为什么要学Nodejs:
  • 一、NodeJs 介绍
    • 1.什么是 Node.js
      • 详解
      • 浏览器、nodejs和其他服务器之间的关系 (更易理解node的定位)
    • 2.node.js特点:
      • 2.1 单线程
      • 2.2 非阻塞 I/O(异步)
      • 2.3 事件驱动
    • 3.Node.js 应用场景:
    • 4.Node.js 模块化/组件化:
  • 二、NodeJS快速入门
    • 1、运行JS文件
    • 2、常用的命令行操作(补充)
    • 3、全局变量
    • 4、导入导出
  • 三、常用内置模块(Nodejs学习的开始)
    • 3.1、os模块
    • 3.2、path模块
    • 3.3、url模块
    • 3.4、url模块
    • 3.5、fs模块
    • 3.6、http模块
      • 3.6.1、介绍
      • 3.6.2、服务器相关概念
      • 3.6.3、创建web服务器
      • 3.6.4、静态资源服务器
      • 3.6.5、get数据获取
      • 3.6.6、post数据获取
  • 总结


前言

提示:Node.js 是一个开源与跨平台的JavaScript运行时环境。它是在浏览器外运行,它是一个事件驱动异步I/O单进程的服务端JS环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
注意:

  • 浏览器是JS的前端运行环境。
  • Node.js是JS的后端运行环境,在后端中运行无法调用 DOM 和 BOM 等浏览器内置 API

前端为什么要学Nodejs:

作为你进击全栈工程师的开始怎么样?


一、NodeJs 介绍

官网参见详解:

  • node官网

  • node中文网

  • node.js社区

1.什么是 Node.js

  • Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
  • Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
  • Node.js 使用了一个事件驱动非阻塞式 I/O 的模型,使其轻量又高效。

详解

简单的说 Node.js 就是运行在服务端的 JavaScript。
- V8引擎本身就是用于Chrome浏览器的JS解释部分。但是Ryan Dahl,把这个V8引擎搬到了服务器上,用于做服务器的软件。
- Node.js是一个让JavaScript运行在服务器端的开发平台,它让JavaScript的触角伸到了服务器端。
- Node.js不是一种独立的语言,与PHP、JSP、Python、Perl、Ruby的“既是语言,也是平台”不同,Node.js使用JavaScript进行编程,运行在JavaScript引擎上(V8)。
- 与PHP、JSP、.net等相比(PHP、JSP、.net都需要运行在服务器程序上,Apache、Nginx、Tomcat、IIS。),Node.js跳过了Apache、Naginx、Tomcat、IIS等HTTP服务器,它自己不用建设在任何服务器软件之上。

浏览器、nodejs和其他服务器之间的关系 (更易理解node的定位)

Nodejs使用教程、及其常用内置模块!web服务器立即创建!_第1张图片

2.node.js特点:

2.1 单线程

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

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

2.2 非阻塞 I/O(异步)

  • 当在访问数据库取得数据的时候,需要一段时间。在传统的单线程处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库返回结果,才能执行后面的代码。也就是说,I/O阻塞了代码的执行,极大地降低了程序的执行效率。
  • 由于Node.js中采用了非阻塞型I/O机制,因此在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率。当某个I/O执行完毕时,将以事件的形式通知执行I/O操作的线程,线程执行这个事件的回调函数。
  • 为了处理异步I/O,线程必须有事件循环,不断的检查有没有未处理的事件,依次予以处理。阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%。
  • 是一种特别有哲理的解决方案:与其人多,但是好多人闲着;还不如一个人玩命,往死里干活儿。

2.3 事件驱动

  • 在Node中,客户端请求建立连接,提交数据等行为,会触发相应的事件。
  • 在Node中,在一个时刻,只能执行一个事件回调函数,但是在执行一个事件回调函数的中途,可以转而处理其他事件(比如,又有新用户连接了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件循环”机制。
  • Node.js底层是C++(V8也是C++写的)。底层代码中,近半数都用于事件队列、回调函数队列的构建。用事件驱动来完成服务器的任务调度,用一个线程,担负起了处理非常多的任务的使命。

注:Node.js是一个让JavaScript运行在服务器端的开发平台,所以必须首先在本机安装Node.js环境

3.Node.js 应用场景:

  • 创建应用服务
  • web开发(后端)
  • 接口开发(小程序)
  • 客户端应用工具如webpack、vue脚手架、react脚手架、小程序等

4.Node.js 模块化/组件化:

NodeJs基于Commonjs模块化开发的规范,它定义一个JS文件就称之为一个模块,(模块化开发,能拆就拆)

  • 在 node 的开发过程中

  • 我们是把每一个功能独立做成一个模块

  • 然后在使用 导入导出 的方式把他们关联在一起

    • 利于维护
    • 准确定位
  • node的模块类型:

    • 内置模块:安装好nodeJS后可以直接使用的模块,也被称之为核心模块

    • 三方模块:需要通过npm/yarn进行安装的模块

    • 自定义模块:开发者自己写的模块,称之为自定义模块

		// 导出(自己定义模块的时候)
		module.exports / exports
		// 导入
		require("module_name")

# 二、NodeJs安装 * 下载安装:[http://nodejs.cn/download/](http://nodejs.cn/download/) * 官网直接下载就可以 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210616220121148.png)
  • msi下载好的东西,是一个安装包,需要我们手动进行,下一步下一步的安装 - 注意:选择安装文件,nodejs的安装路径不要包含中文。(**推荐此方式**

  • zip下载好的东西,是一个压缩文件,解压后,是一个文件夹,这个文件夹就是安装目录,需要手动进行一丢丢的配置。(我们需要自己配置**环境变量**才可以使用)

二、NodeJS快速入门

1、运行JS文件

检查node是否安装成功:

win+r弹出运行窗口
输入cmd
命令行窗口打开后输入:
node -v
出现版本号即为安装成功

如果需要让node运行JavaScript文件,则按照以下语法执行(该操作需要在cmd/命令行/终端/小黑窗中运行):

node 文件路径/js文件

2、常用的命令行操作(补充)

  • 目录操作(操作我们的命令行路径)
1. 查看当前目录下所有文件
     $ dir	 
2. 以树状结构展示当前目录下的所有文件及子目录下的所有文件
	 $ tree	 
3. 进入当前目录下的某一个目录
     $ cd 文件夹名称
4. 返回上一级目录
     $ cd ..
5. 切换盘符
     $ 盘符:
     $ d:
  • 文件操作(通过指令创建文件或者文件夹)
1. 创建文件夹
    # 表示在当前目录下创建一个叫做 test 的文件夹
    $ md test  //或者 mkdir test
2. 移除文件夹
    # 表示移除当前文件夹下的 test 文件夹
    $ rd test  //或者 rmdir test
3. 复制文件夹
    # 表示复制一份 test 文件夹起名为 test2
    $ xcopy test test2
4. 创建文件
    # 表示在当前目录下创建一个叫做 index.js 的文件
    $ type nul> index.js
5. 拷贝一份文件
    # 表示复制一份 index.js 文件起名为 ceshi.js
    $ copy index.js ceshi.js
6. 向文件中写入内容
    # 表示向 index.js 中写入一段文本 console.log('hello world')
    $ echo console.log("hello world") > index.js
7. 查看文件内的文本内容
    # 表示查看 index.js 文件中的文本内容是什么
    $ type index.js
 8. 给文件或者目录重命名
    # 表示把 index.js 更名为 abc.js
    $ ren index.js abc.js
 9. 删除文件
    # 表示把当前目录下的 index.js 删除
    $ del index.js
 10. 移动文件或文件夹
     # 表示把当前目录下的 index.js 文件移动到当前目录下的 a 文件夹下
     $ move index.js a
  • 其他指令
 1. 清屏
    # 表示把当前屏幕的所有内容都清除
    $ cls
 2. 查看当前电脑 IP 信息
    # 表示查看当前电脑的 IP 信息
    $ ipconfig
 3. 测试某一个链接地址的网速
    # 表示查看访问 百度 网站的速度
    $ ping www.baidu.com
 4. 查看电脑信息
    # 表示查看当前电脑的信息
    $ systeminfo
 5. 退出cmd窗口 
    # 表示退出cmd命令提示符窗口
    $ exit  

3、全局变量

  • global:全局变量的宿主(类似于浏览器js中的window对象),这是一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问
  • __filename:当前正在执行的脚本的文件名(完整/绝对路径)
  • __dirname:当前执行脚本所在的目录路径(目录的绝对路径)

4、导入导出

  • 导入
    • 在 node 里面,我们使用 require 来导入一个文件
// 我是 index.js 文件
require('./a.js')
console.log('我是 index.js 文件')
- 当我在命令行运行 `index.js` 文件的时候
- 首先会把 `a.js` 文件运行一遍
- 然后再继续执行我自己文件内部的代码
  • 也可以再导入的时候接受另一个文件导出的内容
// a 接受到的内容就是 a.js 这个文件导出的内容
// 如果 a.js 文件中什么都没有导出,那么接受到的就是一个 空对象
const a = require('./a.js')
  • 导出
    • 我们在写一个 js 文件的时候,可以向外导出一些内容
    • 将来在这个文件被导入的时候,就可以接受到一些内容
// 我是 a.js
// 每一个 js 文件都会有一个对象叫做 module
// 在 module 里面有一个成员,叫做 exports
// 每一个 js 文件会默认把 module.exports 导出
// 也就是说,我们向 module.exports 中添加什么内容
// 那么就会导出什么内容
module.exports.name = 'Jack'
module.exports.age = 18
  • 将来这个文件被导入的时候,接受到的内容就是一个对象,里面有两个成员
// 我是 index.js
const a = require('./a.js')
console.log(a) // { name: 'Jack', age: 18 }

三、常用内置模块(Nodejs学习的开始)

更多内置模块及常用内置模块的更多API用法,可以参考:http://nodejs.cn/api/

3.1、os模块

  • os(operation system)模块提供了与操作系统相关的实用方法和属性。
  • 文档地址:http://nodejs.cn/api/os.html
const os = require('os') // 先导入os模块
// 换行符
os.EOL  //根据操作系统生成对应的换行符 window \r\n,linux下面 \n
// cpu相关信息
os.cpus()
// 总内存大小 (单位 字节)
os.totalmem()
// 空余内存大小 (单位 字节)
os.freemem()
// 主机名
os.hostname()
// 系统类型
os.type()
// ...

3.2、path模块

  • path模块用于处理文件和目录(文件夹)的路径。
const path = require('path')
// 获取路径最后一部内容,一般用它来获取文件名称
path.basename('c:/a/b/c/d.html')  // d.html
// 获取目录名,路径最后分隔符部分被忽略
path.dirname('c:/a/b/c/d.html') // c:/a/b/c
// 获取路径中文件扩展名(后缀)
path.extname('c:/a/b/c/d.html') // .html
// 给定的路径连接在一起
path.join('/a', 'b', 'c') // /a/b/c
// resolve:模拟cd(切换目录)操作同时拼接路径
console.log(path.resolve("a", "b", "c"));
console.log(path.resolve("a", "../b", "c"));
console.log(path.resolve("/a", "b", "c"));
// ...

3.3、url模块

  • URL字符串是结构化的字符串,包含多个含义不同的组成部分。 解析字符串后返回的 URL 对象,每个属性对应字符串的各个组成部分。
    url
const url = require('url');
const href = 'http://www.xxx.com:8080/pathname?id=100#bbb'
// 解析网址,返回Url对象
// 参2 如果为true 则 query获取得到的为对象形式
url.parse(href,true)

//以一种 Web 浏览器解析超链接的方式把一个目标 URL 解析成相对于一个基础 URL。
url.resolve('https://lynnn.cn/foo/bar','bar')

3.4、url模块

  • 用于解析和格式化 URL 查询字符串(URL地址的get形式传参)的实用工具。
const querystring = require('querystring')
//用于get形式传过来的参数
// query字符串转为对象
querystring.parse('foo=bar&abc=xyz')
querystring.decode('foo=bar&abc=xyz')

// 对象转为query字符串
querystring.stringify({ foo: 'bar',abc: 'xyz'})
querystring.encode({ foo: 'bar',abc: 'xyz'})

3.5、fs模块

  • fs(file system)模块提供了用于与文件进行交互相关方法。

注意:fs模块提供了2大类api方法

  • 同步操作
  • 异步操作(回调函数,套娃行为)

后续写代码的时候有2个方案,一个是使用之前套娃式的写法,二是使用同步的api去实现操作。

const fs = require('fs')

// 写入数据(覆盖),追加写使用 fs.appendFile (追加)
fs.writeFile(文件路径,待写入的数据,err => {})

// 读取文件中数据
fs.readFile(文件路径, 'utf8’,(err,data) => {})

// (同步)检查文件是否存在    返回true/false
// async:异步
// sync:同步
let ret = fs.existsSync(path)

// 获取文件信息(异步)
fs.stat(文件,(err,stats) => {
	stats.isDirectory() // 是否是目录
	stats.isFile()       // 是否为文件
	stats.size            // 文件大小(以字节为单位)
})

// 删除文件(异步)
fs.unlink(文件路径,err => {})

3.6、http模块

  • 在讲解该模块时,我们需要了解web服务器的相关内容。

3.6.1、介绍

Web服务器一般指的是网站服务器(服务器:给用户提供服务的机器就是服务器),是指驻留因特网上某一台或N台计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,在服务器上还需要安装服务器软件,目前最主流的三个Web服务器软件是Apache、 Nginx 、IIS

-DNS服务器:动态域名解析系统,作用将域名转化成IP地址

web服务器

3.6.2、服务器相关概念

  • ip地址或域名

ip地址:ip地址有v4和v6之分,IP地址就是互联网上每台计算机/电子设备的唯一地址,因此IP地址具有唯一性。在开发期间,自己的电脑既是一台服务器,也是一个客户端,可以在本机浏览器中输入127.0.0.1进行访问。(IP地址分为公有【用于接入互联网】和私有【组织单元内部的网络,例如:商场、学校、医院、企业等】)

域名:尽管 IP地址能够唯一地标记网络上的计算机,但IP地址是一长串数字,不直观,而且不便于记忆,于是人们又发明了另一套字符型的地址方案,叫域名地址。IP地址和域名是一一对应的关系,这份对应关系存放在一种叫做域名服务器(DNS)的电脑中。在开发测试期间,127.0.0.1 对应的域名是 localhost

本地如果localhost无法使用,则是因为本机中的hosts文件中没有匹配上ip地址:
hosts文件是本地机器的一个域名与ip地址映射关系的文件,充当了dns的作用。

hosts文件

  • 网络协议

网络上的计算机之间交换信息,就像我们说话用某种语言一样,在网络上的各台计算机之间也有一种语言,这就是网络协议,不同的计算机之间必须使用相同的网络协议才能进行通信。如:TCP、UDP、HTTP、FTP等等。

  • 端口号

服务器的端口号就像是现实生活中的门牌号一样。通过门牌号,外卖员就可以准确把外卖送到你的手中。同样的道理,在一台电脑中,可以运行N多个web 服务。每个 web 服务都对应一个唯一的端口号(0-65535,2^16常见的端口号别占用:20,21,22,25,80,443,3306,3389,11211,27017....)。客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的 web 服务进行处理。

注:服务器上的端口号是不可以重复的,必须是独一无二。http服务默认端口号为80,https的端口号默认是443。

扩展:计算机的位数,32位和64位
32位和64位指的是计算机的cpu架构,架构对于计算机有什么影响呢?
最大的影响支持的操作系统的位数,还有影响计算机能够识别的最大内存数量。
32位系统最大能够识别2^32b的内存,理论上是4G,但是实际往往比4G小,大概在3.5-3.9之间。
64位系统最大能够识别2^64b的内存。

3.6.3、创建web服务器

  • NodeJs是通过官方提供的http模块来创建 web服务器的模块。通过几行简单的代码,就能轻松的手写一个web服务,从而对外提供 web 服务

  • 通过下面四个步骤,即可简单创建一个服务器

//1、 导入http模块    
const http = require('http')
//2、 创建web服务对象实例
const server = http.createServer()
//3、 绑定监听客户端请求事件request
// on方法做事件监听
server.on('request', (request, response) => {})

//	request: 接受客户端请求对象,它包含了与客户端相关的数据和属性
//			   request.url      客户端请求的uri地址
//			   request.method  客户端请求的方式 get或post
//			   request.headers	  客户端请求头信息(对象)
//			   ....
//	response:服务器对客户端的响应对象
//			  设置响应头信息 ,用于响应时有中文时乱码解决处理
//			  response.setHeader('content-type', 'text/html;charset=utf-8')
//			  设置状态码(常见的HTTP状态码有:200,404,301、302、304、403、401、405、500,502)
//			  response.statusCode = 200(默认是200)
//			  向客户端发送响应数据,并结束本次请求的处理过程
//			  response.end('hello world')
//4、 启动服务
server.listen(8080, () => {
    console.log('服务已启动')
    // http://127.0.0.1:8080 即可访问
})

案例:手写一个服务器软件,启动后要求用户访问根“/”输出hello world,用户访问/html5输出hello h5

// 1. 导入http模块
const http = require("http");

// 2. 创建web服务实例
const server = http.createServer();

// 3. 监听request请求
server.on("request", (req, res) => {
    // 输出hello world
    // res.end("hello world");
    if (req.url === "/") {
        res.end("hello world");
    }
    if (req.url === "/html5") {
        res.end("hello h5");
    }
});

// 4. 启动服务
server.listen(8080, () => {
    // 仅是提示作用,可以不写,但是建议写
    console.log("server is running at http://127.0.0.1:8080");
});

3.6.4、静态资源服务器

  • 静态资源:常见的有html、css、js、图片、音频、视频

  • 静态资源服务器:专门保存上述静态资源的服务器,称之为静态资源服务器。

  • 实现思路

客户端请求的每个资源uri地址,作为在本机服务器指定目录中的文件。通过相关模块进行读取文件数据进行响应给客户端,从而实现静态服务器。

静态服务器

  • 实现步骤

需求:使用nodejs的http模块创建静态资源服务器,专门存放静态资源展示2张图片

// 创建服务器有以下几步:
//  a. 导入
const http = require("http");
const path = require("path");
const fs = require("fs");
//  b. 创建web实例
const server = http.createServer();
//  c. 监听request事件
server.on("request", (req, res) => {
    // 获取当前用户访问的资源路径
    let uri = req.url;
    // 由于“/”没有实体资源,需要将“/”做处理,如果访问“/”则让其对应访问“/index.html”
    if (uri == "/") {
        uri = "/index.html";
    }
    // 默认情况下,浏览器在第一次请求网站的时候会访问“/favicon.ico”图标文件,如果没有也会出现404
    // 如果需要解决这个问题,则有3种方式:
    // 方式1:去找个ico文件,存放在静态资源的public目录下,命名为“favicon.ico”
    // 方式2:在处理的时候忽略“/favicon.ico”文件的处理,也就是下面的加了判断的写法
    // 方式3:不管,不用处理,其不影响页面的显示
    if(uri != '/favicon.ico'){
        // 读取文件(fs模块),将内容返回给用户(res.end)
        let filename = path.join("public", uri);
        // 判断文件是否存在
        if (fs.existsSync(filename)) {
            fs.readFile(filename, (err, data) => {
                if (!err) {
                    // ok
                    res.end(data);
                } else {
                    // 不ok
                    res.setHeader("Content-Type", "text/html;charset=utf-8");
                    res.statusCode = 500;
                    res.end("请求资源出现错误。。。");
                }
            });
        } else {
            res.setHeader("Content-Type", "text/html;charset=utf-8");
            res.statusCode = 404;
            res.end("你要找的资源失踪了。。。");
        }
    }
});
//  d. 监听端口,启动服务
server.listen(8080, () => {
    console.log("server is running at http://127.0.0.1:8080");
});

3.6.5、get数据获取

  • get数据通过地址栏使用query方式进行传递的数据 例id=1&name=zhangsan
// 导入
const http = require('http');
const url = require('url');
// 创建实例&监听request事件&监听端口
http.createServer((req, res) => {
    //  之前第3步中的回调函数
	// 获取地址栏中 query数据
	let { query } = url.parse(req.url, true);
	console.log(query);
}).listen(8080)

3.6.6、post数据获取

  • 表单数据多数为post进行提交到服务器端。需要监听req对象的data事件(接收请求提交过来的数据的)来获取客户端发送到服务器的数据。如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后分批次发送给服务器所以data事件可能会被触发多次,每次触发data事件时,收到的数据只是全部数据的一部分,因此需要做数据的拼接才能得到完整的数据:
const http = require('http');
const queryString = require('querystring');
http.createServer((req, res) => {
    let arr = [];
    // 数据接受中
    req.on('data', buffer => {
        arr.push(buffer);
    });
    // 数据传输结束了
    req.on('end', () => {
        // 拼接接受到的所有数据
        let buffer = Buffer.concat(arr);
        let post = queryString.parse(buffer.toString())
        console.log(post);
    });
}).listen(8080)

  • 注:上面是使用 软件· Postman 模拟客户端post请求

总结

  • Nodejs是一个可以让javascript在浏览器外运行的JS环境
  • 学习一些内置插件能使我们在学习其他第三方插件时更得心应手
  • 希望对正在学习的有所帮助。

你可能感兴趣的:(nodejs,node.js,javascript)