Node汇总

目录

1.Node开发概述

  1.1服务器端开发要做的事情

1.2Node是什么

2.Node运行环境搭建

2.1 Node.js运行环境安装

2.2 Node环境安装失败解决办法

1. 错误代号2502、2503

2.3 PATH环境变量

3.Node.js快速入门

3.1 Node.js 的组成

3.2 Node.js基础语法

3.3 Node.js全局对象global

4.Node.js模块化开发

4.1JavaScript开发弊端

4.2Node.js中模块化开发规范

4.3 模块成员的导入

5.系统模块

5.1什么是系统模块

5.2系统模块fs 文件操作

5.3 系统模块path 路径操作

5.4路径拼接语法

5.5相对路径VS绝对路径

6.第三方模块

6.1第三方模块有两种存在形式:

6.2 获取第三方模块

6.3 第三方模块 nodemon

6.4 第三方模块 nrm

6.5 第三方模块 Gulp

6.6  Gulp能做什么

6.7 Gulp使用

6.8Gulp中提供的方法

6.9 Gulp插件

7.package.json文件

7.1 node_modules文件夹的问题

7.2  package.json文件的作用:记录当前项目信息

7.3 项目依赖

7.4 开发依赖

7.5 package-lock.json文件的作用:详细记录了模块与模块间的依赖关系

8. Node.js中模块加载机制

8.1 模块查找规则-当模块拥有路径但没有后缀时

8.2 模块查找规则-当模块没有路径且没有后缀时

9.服务器端基础概念

    9.1网站的组成

9.2IP地址

9.3域名域名

9.4端口

9.5URL

9.5.1URL的组成

9.6开发过程中客户端和服务器端说明

10.创建web服务器

11.HTTP协议

11.1 HTTP协议的概念

11.2报文

11.3请求报文

11.3.1. 请求方式 (Request Method)

11.3.2. 请求地址 (Request URL)

11.4响应报文

11.4.1HTTP状态码

11.4.2内容类型

12.HTTP请求与响应处理

12.1 请求参数

12.2 GET请求参数

12.3 POST请求参数

12.4 路由

12.5 静态资源

12.6 动态资源

12.7 客户端请求路径

12.7.1 GET方式

12.7.2 POST方式

13.Node.js异步编程

13.1 同步API, 异步API

13.1.1 同步API:只有当前API执行完成后,才能继续执行下一个API

13.1.2 异步API:当前API的执行不会阻塞后续代码的执行

13.2 同步API, 异步API的区别( 获取返回值 )

13.3 回调函数

13.4 使用回调函数获取异步API执行结果

13.5 同步API, 异步API的区别(代码执行顺序)

13.6 代码执行顺序分析

13.7 Node.js中的异步API

13.8 Promise

13.9 异步函数

1.Node开发概述

  1.1服务器端开发要做的事情

  • l实现网站的业务逻辑
  • l数据的增删改查

1.2Node是什么

Node是一个基于Chrome V8引擎的JavaScript代码运行环境

2.Node运行环境搭建

2.1 Node.js运行环境安装

官网:https://nodejs.org/en/

检测是否安装成功:打开命令行工具cmd--node -v 如果显示版本号则表示安装成功

2.2 Node环境安装失败解决办法

1. 错误代号2502、2503

失败原因:系统帐户权限不足。

解决办法:

1. 以管理员身份运行 powershell 命令行工具
2. 输入运行安装包命令 msiexec  /package node 安装包位置
 
2. 执行命令报错
 
失败原因: Node 安装目录写入环境变量失败
 
解决办法:将 Node 安装目录添加到环境变量中   电脑右击--属性--高级系统设置--高级--环境变量--系统变量中的path双击--新建--将node安装的路径粘贴进去
 

2.3 PATH环境变量

3.Node.js快速入门

3.1 Node.js 的组成

  • lJavaScript 由三部分组成,ECMAScriptDOMBOM。
  • lNode.js是由ECMAScriptNode 环境提供的一些附加API组成的,包括文件、网络、路径等等一些更加强大的 API
 
 

3.2 Node.js基础语法

在Node环境下执行代码,使用Node命令执行后缀为.js的文件即可

运行js文件:再文件所在位置右击--打开powershell窗口--node 01.helloworld.js(输入01按下tab键,命令行工具会自动补全js文件名)

3.3 Node.js全局对象global

     在浏览器中全局对象是window,在Node中全局对象是global

Node中全局对象下有以下方法,可以在任何地方使用,global可以省略。

  • lconsole.log()     在控制台中输出
  • lsetTimeout()     设置超时定时器
  • lclearTimeout()  清除超时时定时器
  • lsetInterval()      设置间歇定时器
  • lclearInterval()   清除间歇定时器

4.Node.js模块化开发

4.1JavaScript开发弊端

JavaScript在使用时存在两大问题,文件依赖命名冲突。

4.2Node.js中模块化开发规范

  • lNode.js规定一个JavaScript文件就是一个模块,模块内部定义的变量和函数默认情况下在外部无法得到
  • l模块内部可以使用exports对象进行成员导出, 使用require方法导入其他模块。

4.3 模块成员的导入

// b.js
  // 在b.js模块中导入模块a
 let a = require('./b.js');
  // 输出b模块中的version变量
 console.log(a.version);
  // 调用b模块中的sayHi方法 并输出其返回值
 console.log(a.sayHi('黑马讲师')); 

5.统模块

5.1什么是系统模块

Node运行环境提供的API. 因为这些API都是以模块化的方式进行开发的, 所以我们又称Node运行环境提供的API为系统模块

5.2系统模块fs 文件操作

ffile 文件 ,ssystem 系统,文件操作系统。

const fs = require('fs');

读取文件内容

fs.reaFile('文件路径/文件名称'[,'文件编码'], callback);

写入文件内容

fs.writeFile('文件路径/文件名称', '数据', callback);


const content = '<h3>正在使用fs.writeFile写入文件内容</h3>';
 fs.writeFile('../index.html', content, err => {
   if (err != null) { 
       console.log(err);
       return;
   }
   console.log('文件写入成功');
 });

5.3 系统模块path 路径操作

5.4路径拼接语法

path.join('路径', '路径', ...)



// 导入path模块
 const path = require('path');
  // 路径拼接
 let finialPath = path.join('itcast', 'a', 'b', 'c.css');
  // 输出结果 itcast\a\b\c.css
 console.log(finialPath);

5.5对路径VS绝对路径

  • l大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录
  • l在读取文件或者设置文件路径时都会选择绝对路径
  • l使用__dirname获取当前文件所在的绝对路径

6.第三方模块

6.1第三方模块有两种存在形式

  • ljs文件的形式存在,提供实现项目具体功能的API接口
  • l以命令行工具形式存在,辅助项目开发

6.2 获取第三方模块

npmjs.com:第三方模块的存储和分发仓库

npm (node package manager) node的第三方模块管理工具

  • l下载:npm install 模块名称  例如:npm install formidable
  • l卸载:npm unintall package 模块名称  例如:npm uninstall formidable

   全局安装与本地安装

  • l命令行工具:全局安装
  • l库文件:本地安装

6.3 第三方模块 nodemon

nodemon是一个命令行工具,用以辅助项目开发。

Node.js中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。

使用步骤

1. 使用 npm install nodemon –g 下载它(-g意思是全局安装即global)
2. 在命令行工具中用 nodemon 命令替代 node 命令执行文件
**按两次ctrl+c 即可以停止命令行工具运行

6.4 第三方模块 nrm

nrm ( npm registry manager )npm下载地址切换工具

npm默认的下载地址在国外,国内下载速度慢(淘宝npm镜像问题)

使用步骤

1. 使用" npm install nrm –g " 下载它
2. 查询可用下载地址列表 " nrm ls"(这个命令可以查看所有需要下载地址的列表)
3. 切换 npm 下载地址 nrm use 下载地址名称
 
 

6.5 第三方模块 Gulp

基于node平台开发的前端构建工具

将机械化操作编写成任务, 想要执行机械化操作时执行一个命令行命令任务就能自动执行了

用机器代替手工,提高开发效率
 

6.6  Gulp能做什么

  • l项目上线,HTMLCSSJS文件压缩合并
  • l语法转换(es6、less ...)
  • l公共文件抽离
  • l修改文件浏览器自动刷新

6.7 Gulp使用

1. 使用 npm install gulp 下载 gulp 库文件
2. 在项目根目录下建立 gulpfile.js 文件
3. 重构项目的文件夹结构 src 目录放置源代码文件 dist 目录放置构建后文件
4. gulpfile.js 文件中编写任务 .
5. 在命令行工具中执行 gulp 任务
 
 

6.8Gulp中提供的方法

  • lgulp.src():获取任务要处理的文件
  • lgulp.dest():输出文件
  • lgulp.task():建立gulp任务
  • gulp.watch():监控文件的变化
 const gulp = require('gulp');
  // 使用gulp.task()方法建立任务
 gulp.task('first', () => {
    // 获取要处理的文件
    gulp.src('./src/css/base.css') 
    // 将处理后的文件输出到dist目录
    .pipe(gulp.dest('./dist/css'));
 });
// 引用gulp模块
const gulp = require('gulp');
// 使用gulp.task建立任务
// 1.任务的名称
// 2.任务的回调函数
gulp.task('first', () => {
	console.log('我们人生中的第一个gulp任务执行了');
	// 1.使用gulp.src获取要处理的文件,使用pipe处理文件,并放到了dist/css目录下
	gulp.src('./src/css/base.css')
		.pipe(gulp.dest('dist/css'));
});

6.9 Gulp插件

  • lgulp-htmlmin :html文件压缩
  • lgulp-csso :压缩css
  • lgulp-babel :JavaScript语法转化
  • lgulp-less: less语法转化
  • lgulp-uglify :压缩混淆JavaScript
  • lgulp-file-include 公共文件包含
  • lbrowsersync 浏览器实时同步

使用步骤:

  • 下载:在命令行中输入“npm install gulp-htmlmin”
  • 引用:const htmlmin = require('gulp-htmlmin');
  • 编写任务,调用插件:
    gulp.task('htmlmin', () => {
    	gulp.src('./src/*.html')
    		.pipe(fileinclude())
    		// 压缩html文件中的代码
    		.pipe(htmlmin({ collapseWhitespace: true }))
    		.pipe(gulp.dest('dist'));
    });
    
  • 运行:在命令行中输入:“glup htmlmin”

抽取公共页面header.html

在原文件中使用语句:@@include('./common/header.html')进行引用

gulpfile.js

// 引用gulp模块
const gulp = require('gulp');
const htmlmin = require('gulp-htmlmin');
const fileinclude = require('gulp-file-include');
const less = require('gulp-less');
const csso = require('gulp-csso');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
// 使用gulp.task建立任务
// 1.任务的名称
// 2.任务的回调函数
gulp.task('first', () => {
	console.log('我们人生中的第一个gulp任务执行了');
	// 1.使用gulp.src获取要处理的文件
	gulp.src('./src/css/base.css')
		.pipe(gulp.dest('dist/css'));
});

// html任务
// 1.html文件中代码的压缩操作
// 2.抽取html文件中的公共代码
gulp.task('htmlmin', () => {
	gulp.src('./src/*.html')
		.pipe(fileinclude())
		// 压缩html文件中的代码
		.pipe(htmlmin({ collapseWhitespace: true }))
		.pipe(gulp.dest('dist'));
});

// css任务
// 1.less语法转换
// 2.css代码压缩
gulp.task('cssmin', () => {
	// 选择css目录下的所有less文件以及css文件
	gulp.src(['./src/css/*.less', './src/css/*.css'])
		// 将less语法转换为css语法
		.pipe(less())
		// 将css代码进行压缩
		.pipe(csso())
		// 将处理的结果进行输出
		.pipe(gulp.dest('dist/css'))
});

// js任务
// 1.es6代码转换
// 2.代码压缩
gulp.task('jsmin', () => {
	gulp.src('./src/js/*.js')
		.pipe(babel({
			// 它可以判断当前代码的运行环境 将代码转换为当前运行环境所支持的代码
            presets: ['@babel/env']
        }))
        .pipe(uglify())
        .pipe(gulp.dest('dist/js'))
});

// 复制文件夹
gulp.task('copy', () => {

	gulp.src('./src/images/*')
		.pipe(gulp.dest('dist/images'));

	gulp.src('./src/lib/*')
		.pipe(gulp.dest('dist/lib'))
});

// 构建任务
gulp.task('default', ['htmlmin', 'cssmin', 'jsmin', 'copy']);

 

7.package.json文件

7.1 node_modules文件夹的问题

1. 文件夹以及文件过多过碎,当我们将项目整体拷贝给别人的时候 , ,传输速度会很慢很慢 .
2. 复杂的模块依赖关系需要被记录,确保模块的版本和当前保持一致,否则会导致当前项目运行报错

7.2  package.json文件的作用:记录当前项目信息

项目描述文件,记录了当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了哪些第三方模块等。

使用npm init -y命令生成package.json文件。

7.3 项目依赖

  • l在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖
  • l使用npm install 包名命令下载的文件会默认被添加到 package.json 文件的 dependencies 字段中

**输入命令"npm install"即安装了全部的依赖--项目依赖和开发依赖

**如果只想安装项目依赖,输入命令:"npm install --production"

 {
    "dependencies": {
        "jquery": "^3.3.1“
    }
 } 

7.4 开发依赖

  • l在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖
  • l使用npm install 包名 --save-dev命令将包添加到package.json文件的devDependencies字段中
 {
    "devDependencies": {
        "gulp": "^3.9.1“
    }
 } 

7.5 package-lock.json文件的作用:详细记录了模块与模块间的依赖关系

  • l锁定包的版本,确保再次下载时不会因为包版本不同而产生问题
  • l 加快下载速度,因为该文件中已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可,不需要做额外的工作

8. Node.js中模块加载机制

8.1 模块查找规则-当模块拥有路径没有后缀时

require('./find.js');

require('./find');
1. require 方法根据模块路径查找模块,如果是完整路径,直接引入模块
2. 如果模块后缀 省略 ,先 找同名 JS 文件再找同名 JS 文件夹
3. 如果找到了同名文件夹,找 文件夹中的 index.js
4. 如果文件夹中没有 index.js 就会去当前文件夹中的 package.json 文件中 查找 main 选项中的入口 文件
5. 如果 找指定的入口文件不存在或者没有指定入口文件就会 错,模块没有被找到
 

8.2 模块查找规则-当模块没有路径且没有后缀时

require('find');
1. Node.js会假设它是系统模块
2. Node .js会去node_modules文件夹中
3. 首先看是否有该名字的JS文件
4. 再看是否有该名字的文件夹
5. 如果是文件夹看里面是否有index. js
6. 如果没有index.js查看该文件夹中的package.json中的main选项确定模块入口文件
7. 否则找不到报错
 

9.服务器端基础概念

    9.1网站的组成

网站应用程序主要分为两大部分:客户端和服务器端。

客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTMLCSSJavaScript构建。

服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。

9.2IP地址

互联网中设备的唯一标识。

IPInternet Protocol Address的简写,代表互联网协议地址.

9.3域名域名

由于IP地址难于记忆,所以产生了域名的概念,所谓域名就是平时上网所使用的网址

http://www.itheima.com  =>  http://124.165.219.100/

虽然在地址栏中输入的是网址, 但是最终还是会将域名转换为ip才能访问到指定的网站服务器。

9.4端口

端口是 计算机 外界通讯交流的出口,用来区分服务器电脑中提供的不同的 服务。

9.5URL

统一资源定位符,又叫URL(Uniform Resource Locator),是专为标识Internet网上资源位置而设的一种编址方式,我们平时所说的网页地址指的即是URL

9.5.1URL的组成

传输协议://服务器IP或域名:端口/资源所在位置标识

http://www.itcast.cn/news/20181018/09152238514.html

http:超文本传输协议,提供了一种发布和接收HTML页面的方法

9.6开发过程中客户端和服务器端说明

 

本机域名:localhost

本地IP   127.0.0.1

10.创建web服务器

  // 引用系统模块
 const http = require('http');
  // 创建web服务器
 const app = http.createServer();
  // 当客户端发送请求的时候  
  //request为事件名称,第二个参数为事件处理函数,包括两个参数req(request)表示请求对象,比如请求地址等;res(response)表示响应对象,使用下面的方法对客户端发来的请求进行响应
 app.on('request', (req, res) => {
        // 使用end方法进行响应
       res.end('<h1>hi, user</h1>');
 });
  // 监听3000端口
 app.listen(3000);
 console.log('服务器已启动,监听3000端口,请访问 localhost:3000')

11.HTTP协议

11.1 HTTP协议的概念

超文本传输协议 (英文: HyperText  Transfer Protocol ,缩写: HTTP )规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。
 

11.2报文

HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式。

11.3请求报文

11.3.1. 请求方式 (Request Method)

  • GET     请求数据(获取数据的请求)
  • POST   发送数据(添加数据的请求)

** 请求既不是获取数据也不是添加数据,就是一般逻辑,用post请求

Post表单请求

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<!--
		method: 指定当前表单提交的方式
		action: 指定当前表单提交的地址
	-->
	<form method="post" action="http://localhost:3000">
		<input type="text" name="username">
		<input type="password" name="password">
		<input type="submit">
	</form>
</body>
</html>

 

11.3.2. 请求地址 (Request URL)

app.on('request', (req, res) => {
     req.headers  // 获取请求报文
     req.url      // 获取请求地址
     req.method   // 获取请求方法
 });
// 用于创建网站服务器的模块
const http = require('http');
// 用于处理url地址
const url = require('url');
// app对象就是网站服务器对象
const app = http.createServer();
// 当客户端有请求来的时候
app.on('request', (req, res) => {
	// 获取请求方式
	// req.method
	// console.log(req.method);
	
	// 获取请求地址
	// req.url
	// console.log(req.url);
	
	// 获取请求报文信息
	// req.headers
	// console.log(req.headers['accept']);
	
	res.writeHead(200, {
		'content-type': 'text/html;charset=utf8'
	});

	console.log(req.url);
	// 1) 要解析的url地址
	// 2) 将查询参数解析成对象形式
    //query表示请求对象,pahtname为不包含请求参数的请求地址
	let { query, pathname } = url.parse(req.url, true);
	console.log(query.name)
	console.log(query.age)

	if (pathname == '/index' || pathname == '/') {
		res.end('<h2>欢迎来到首页</h2>');
	}else if (pathname == '/list') {
		res.end('welcome to listpage');
	}else {
		res.end('not found');
	}
	
	if (req.method == 'POST') {
		res.end('post')
	} else if (req.method == 'GET') {
		res.end('get')
	}

	// res.end('<h2>hello user</h2>');
});
// 监听端口
app.listen(3000);
console.log('网站服务器启动成功');

 

11.4响应报文

11.4.1HTTP状态码

  • 200 请求成功
  • 404 请求的资源没有被找到
  • 500 服务器端错误
  • 400 客户端请求有语法错误

 运行页面后,可以在调试工具的Network项中看到状态码

11.4.2内容类型

  • text/html
  • text/css
  • application/javascript
  • image/jpeg
  • application/json
app.on('request', (req, res) => {
     // 设置响应报文
     res.writeHead(200, {         'Content-Type': 'text/html;charset=utf8‘
     });
 });

12.HTTP请求与响应处理

12.1 请求参数

客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作。

Get与Post请求参数的不同?

get请求参数放在地址栏中,而post请求参数在调试工具的Network中 

12.2 GET请求参数

  • 参数被放置在浏览器地址栏中,例如:http://localhost:3000/?name=zhangsan&age=20
  • 参数获取需要借助系统模块urlurl模块用来处理url地址
//借助系统模块url,在系统模块url下有个parse方法,parse方法是用来处理url地址,把url地址处理成对象形式,在对象里保存了url地址的部分,
const http = require('http');
 // 导入url系统模块 用于处理url地址
 const url = require('url');
 const app = http.createServer();
 app.on('request', (req, res) => {
     // 将url路径的各个部分解析出来并返回对象
         // true 代表将参数解析为对象格式
     let {query} = url.parse(req.url, true);  
     console.log(query);
 });
 app.listen(3000);

12.3 POST请求参数

  • l参数被放置在请求体中进行传输(参数被放在了url地址中)
  • l获取POST参数需要使用data事件和end事件(获取GET参数使用req的url就可以)
  • l使用querystring系统模块将参数转换为对象格式(querystring中的parse方法可以将字符串类型转换为对象格式)
 // 导入系统模块querystring 用于将HTTP参数转换为对象格式
 const querystring = require('querystring');
 app.on('request', (req, res) => {
     let postData = '';
     // 监听参数传输事件,当触发data事件的时候,将chunk与postdata进行一个拼接
     req.on('data', (chunk) => postData += chunk;);
     // 监听参数传输完毕事件
     req.on('end', () => { 
        console.log(querystring.parse(postData)); //使用querystring.parse方法对格式进行了处理
     }); 
 });

12.4 路由

http://localhost:3000/index

http://localhost:3000/login

路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。

// 当客户端发来请求的时候
 app.on('request', (req, res) => {
     // 获取客户端的请求路径
     let { pathname } = url.parse(req.url);
     if (pathname == '/' || pathname == '/index') {
         res.end('欢迎来到首页');
     } else if (pathname == '/list') {
         res.end('欢迎来到列表页页');
     } else {
        res.end('抱歉, 您访问的页面出游了');
     }
 });
// 1.引入系统模块http
// 2.创建网站服务器
// 3.为网站服务器对象添加请求事件
// 4.实现路由功能
// 	1.获取客户端的请求方式
// 	2.获取客户端的请求地址
const http = require('http');
const url = require('url');

const app = http.createServer();

app.on('request', (req, res) => {
	// 获取请求方式
	const method = req.method.toLowerCase();
	// 获取请求地址 通过url.parse将req.url地址解析成各个部分
	const pathname = url.parse(req.url).pathname;

	res.writeHead(200, {
		'content-type': 'text/html;charset=utf8'
	});

	if (method == 'get') {

		if (pathname == '/' || pathname == '/index') {
			res.end('欢迎来到首页')
		}else if (pathname == '/list') {
			res.end('欢迎来到列表页')
		}else {
			res.end('您访问的页面不存在')
		}

	}else if (method == 'post') {

	}

});

app.listen(3000);
console.log('服务器启动成功')

12.5 静态资源

服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。

const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');

const app = http.createServer();

app.on('request', (req, res) => {
	// 获取用户的请求路径
	let pathname = url.parse(req.url).pathname;

	pathname = pathname == '/' ? '/default.html' : pathname;

	// 将用户的请求路径转换为实际的服务器硬盘路径
	let realPath = path.join(const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');

const app = http.createServer();

app.on('request', (req, res) => {
	// 获取用户的请求路径
	let pathname = url.parse(req.url).pathname;

	pathname = pathname == '/' ? '/default.html' : pathname;

	// 将用户的请求路径转换为实际的服务器硬盘路径   const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');

const app = http.createServer();

app.on('request', (req, res) => {
	// 获取用户的请求路径
	let pathname = url.parse(req.url).pathname;

	pathname = pathname == '/' ? '/default.html' : pathname;

	// 将用户的请求路径转换为实际的服务器硬盘路径   __dirname获取当前文件的绝对路径
	let realPath = path.join(__dirname, 'public' + pathname);

	let type = mime.getType(realPath)

	// 读取文件
	fs.readFile(realPath, (error, result) => {
		// 如果文件读取失败
		if (error != null) {
			res.writeHead(404, {
				'content-type': 'text/html;charset=utf8'
			})
			res.end('文件读取失败');
			return;
		}

		res.writeHead(200, {
			'content-type': type
		})

		res.end(result);
	});
});

app.listen(3000);
console.log('服务器启动成功')
	let realPath = path.join(__dirname, 'public' + pathname);

	let type = mime.getType(realPath)

	// 读取文件
	fs.readFile(realPath, (error, result) => {
		// 如果文件读取失败
		if (error != null) {
			res.writeHead(404, {
				'content-type': 'text/html;charset=utf8'
			})
			res.end('文件读取失败');
			return;
		}

		res.writeHead(200, {
			'content-type': type
		})

		res.end(result);
	});
});

app.listen(3000);
console.log('服务器启动成功'), 'public' + pathname);

	let type = mime.getType(realPath)

	// 读取文件
	fs.readFile(realPath, (error, result) => {
		// 如果文件读取失败
		if (error != null) {
			res.writeHead(404, {
				'content-type': 'text/html;charset=utf8'
			})
			res.end('文件读取失败');
			return;
		}

		res.writeHead(200, {
			'content-type': type
		})

		res.end(result);
	});
});

app.listen(3000);
console.log('服务器启动成功')

 

12.6 动态资源

相同的请求地址不同的响应资源,这种资源就是动态资源。

http://www.itcast.cn/article?id=1

http://www.itcast.cn/article?id=2

12.7 客户端请求路径

12.7.1 GET方式

  • 浏览器地址栏
  • link标签的href属性
  • script标签的src属性
  • img标签的src属性
  • Form表单提交

12.7.2 POST方式

  • Form表单提交
 

13.Node.js异步编程

13.1 同步API, 异步API

 // 路径拼接
 const public = path.join(__dirname, 'public');
 // 请求地址解析
 const urlObj = url.parse(req.url);
 // 读取文件
 fs.readFile('./demo.txt', 'utf8', (err, result) => {
     console.log(result);
 });

13.1.1 同步API:只有当前API执行完成后,才能继续执行下一个API

console.log('before'); 
console.log('after');

13.1.2 异步API:当前API的执行不会阻塞后续代码的执行

console.log('before');
setTimeout(
   () => { console.log('last');
}, 2000);
console.log('after');

13.2 同步API, 异步API的区别( 获取返回值 )

同步API可以从返回值中拿到API执行的结果, 但是异步API是不可以的

// 同步
  function sum (n1, n2) { 
      return n1 + n2;
  } 
  const result = sum (10, 20);


    // 异步
  function getMsg () { 
      setTimeout(function () { 
          return { msg: 'Hello Node.js' }
      }, 2000);
  }
  const msg = getMsg ();
  console.log(msg);

说明在异步API中无法直接拿到API的返回值,需要使用回调函数来实现拿到返回值

13.3 回调函数

自己定义函数让别人去调用。

// getData函数定义
 function getData (callback) {}
  // getData函数调用
 getData (() => {});

 

function getData (callback) {
	callback('123')
}

getData(function (n) {
	console.log('callback函数被调用了')
	console.log(n)
});

通过回调函数拿到异步API的执行结果实例

 

13.4 使用回调函数获取异步API执行结果

function getMsg (callback) {
    setTimeout(function () {
        callback ({ msg: 'Hello Node.js' })
    }, 2000);
}
getMsg (function (msg) { 
    console.log(msg);
});

13.5 同步API, 异步API的区别(代码执行顺序)

同步API从上到下依次执行,前面代码会阻塞后面代码的执行

for (var i = 0; i < 100000; i++) { 
    console.log(i);
}
console.log('for循环后面的代码');

异步API不会等待API执行完成后再向下执行代码

console.log('代码开始执行'); 
setTimeout(() => { console.log('2秒后执行的代码')}, 2000);
setTimeout(() => { console.log('"0秒"后执行的代码')}, 0); 
console.log('代码结束执行');

13.6 代码执行顺序分析

console.log('代码开始执行');
setTimeout(() => {
    console.log('2秒后执行的代码');
}, 2000); 
setTimeout(() => {
    console.log('"0秒"后执行的代码');
}, 0);
console.log('代码结束执行');

将所有的同步API执行完之后再执行异步API

13.7 Node.js中的异步API

fs.readFile('./demo.txt', (err, result) => {});


var server = http.createServer();
server.on('request', (req, res) => {});

如果异步API后面代码的执行依赖当前异步API的执行结果,但实际上后续代码在执行的时候异步API还没有返回结果,这个问题要怎么解决呢?

fs.readFile('./demo.txt', (err, result) => {});
console.log('文件读取结果');

需求:依次读取1文件、2文件、3文件

const fs = require('fs');

fs.readFile('./1.txt', 'utf8', (err, result1) => {
	console.log(result1)
	fs.readFile('./2.txt', 'utf8', (err, result2) => {
		console.log(result2)
		fs.readFile('./3.txt', 'utf8', (err, result3) => {
			console.log(result3)
		})
	})
});

13.8 Promise

Promise出现的目的是解决Node.js异步编程中回调地狱的问题。
 
//resolve是一个函数,将异步API有返回结果的时候可以去调用这个函数,并且将异步API返回的结果通过参数的形式传出去
//reject是一个函数,传送失败了,使用这个函数将结果传送到Promise外面去
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        if (true) {
            resolve({name: '张三'})
        }else {
            reject('失败了') 
        } 
    }, 2000);
});
promise.then(result => console.log(result); // {name: '张三'})
       .catch(error => console.log(error); // 失败了)
const fs = require('fs');

// fs.readFile('./1.txt', 'utf8', (err, result1) => {
// 	console.log(result1)
// 	fs.readFile('./2.txt', 'utf8', (err, result2) => {
// 		console.log(result2)
// 		fs.readFile('./3.txt', 'utf8', (err, result3) => {
// 			console.log(result3)
// 		})
// 	})
// });

function p1 () {
	return new Promise ((resolve, reject) => {
		fs.readFile('./1.txt', 'utf8', (err, result) => {
			resolve(result)
		})
	});
}

function p2 () {
	return new Promise ((resolve, reject) => {
		fs.readFile('./2.txt', 'utf8', (err, result) => {
			resolve(result)
		})
	});
}

function p3 () {
	return new Promise ((resolve, reject) => {
		fs.readFile('./3.txt', 'utf8', (err, result) => {
			resolve(result)
		})
	});
}

p1().then((r1)=> {
	console.log(r1);
	return p2();
})
.then((r2)=> {
	console.log(r2);
	return p3();
})
.then((r3) => {
	console.log(r3)
})

13.9 异步函数

异步函数就是在基于promise的基础上,进行了封装,将繁琐的代码封装起来,开放一些关键字供我们来使用

异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。

const fn = async () => {};


async function fn () {}

async关键字

1. 普通函数定义前加async关键字 普通函数变成异步函数

2. 异步函数默认返回promise对象

3. 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法

4. 在异步函数内部使用throw关键字抛出程序异常

5. 调用异步函数再链式调用then方法获取异步函数执行结果

6. 调用异步函数再链式调用catch方法获取异步函数执行的错误信息

await关键字

1. await关键字只能出现在异步函数中

2. await promise await后面只能写promise对象 写其他类型的API是不不可以的

3. await关键字可是暂停异步函数向下执行 直到promise返回结果再往下执行

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值