IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【笔记】Promise入门到实现 -> 正文阅读

[JavaScript知识库]【笔记】Promise入门到实现

一、介绍与基本使用

1. Promise理解

a. 抽象表达:
	i. 新技术(ES规范)、异步编程的新解决方案
	ii. 异步编程(回调函数):fs文件操作、数据库操作、AJAX、定时器
b. 具体表达:
	i. 语法上:构造函数

2. 为什么使用?

a. 指定回调函数的方式更加灵活
	i. 旧:启动异步任务前指定;
	ii. promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数
b. 支持链式调用,解决回调地狱问题(回调函数嵌套调用,不便于阅读与异常处理)	

3. promise的状态

a. 实例对象中的一个属性:【PromiseState】
b. 状态只能改变一次,且由pending开始转换:pending 未决定的;resolved / fullfilled 成功;rejected 失败

4. promise的值

a. 实例对象中的一个属性:【PromiseResult】
b. 异步任务 对象 成功 / 失败 的结果,resolve() 与 reject()可修改

5. Promise基本流程

在这里插入图片描述

二、Promise API

1. Promise 构造函数: Promise (excutor) {}

a. 执行器函数executor : (resolve, reject) => {} ,在 Promise 内部立即同步调用,异步操作在执行器中执行
b. resolve 函数: 内部定义成功时我们调用的函数 value => {} 
c. reject 函数: 内部定义失败时我们调用的函数 reason => {}

2. Promise.prototype.then 方法: (onResolved, onRejected) => {}

a. onResolved 函数: 成功 value 的回调函数 (value) => {} 
b. onRejected 函数: 失败reason 的回调函数 (reason) => {} 

3. Promise.prototype.catch 方法: (onRejected) => {}

a. onRejected 函数: 失败的回调函数 (reason) => {}
b. then()的语法糖, 相当于: then(undefined, onRejected) 

4. Promise.resolve 方法: (value) => {}

a.  value: 成功的数据或 promise 对象,返回一个成功/失败的 promise 对象
b. 快速返回或封装一个promise对象

????在这里插入图片描述

5. Promise.reject 方法: (reason) => {}

a. reason: 失败的原因,快速返回一个失败的 promise 对象 
b. 传入任何类型的对象,仍返回失败的promise对象	

6. Promise.all 方法: (promises) => {}

a. promises: 包含 n 个 promise 的数组 
b. 说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败 

7. Promise.race 方法: (promises) => {}

a.  promises: 包含 n 个 promise 的数组 
b. 说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

三、关键问题

1. 如何改变 promise 的状态?

a. resolve(value): 如果当前是 pending 就会变为 resolved 
b. reject(reason): 如果当前是 pending 就会变为 rejected 
c. 抛出异常: 如果当前是 pending 就会变为 rejected

2. 一个 promise

指定多个成功/失败回调函数, 都会调用吗:当 promise 改变为对应状态时都会调用

3. 改变 promise 状态和指定回调函数谁先谁后?

a. 都有可能:正常情况下先指定回调再改变状态; 但也可以先改状态再指定回调 
b. 如何先改状态再指定回调? 
	i. 同步任务:在执行器中直接调用 resolve()/reject() 
	ii. 延迟更长时间才调用 then() 
c.  什么时候才能得到数据? 
	i. 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据 
	ii. 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据

4. promise.then()返回的新 promise对象的结果状态由什么决定?

a.  简单表达: 由 then()指定的回调函数执行的结果决定 
b. 详细表达: 
	i. 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常 
	ii. 如果返回的是非 promise 的任意值(eg,return xxx;), 新 promise 变为 resolved, value 为返回的值 
	iii. 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果 

5. promise 如何串连多个操作任务?

a.  promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
b.  通过 then 的链式调用串连多个同步/异步任务

6. promise 异常传透?

a. 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调, 
b.  前面任何操作出了异常, 都会传到最后失败的回调中处理

7. 中断 promise 链?

a. 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
b. 办法: 在回调函数中返回一个 pendding 状态的 promise 对象

????在这里插入图片描述

四、自定义封装

class Promise {
	// 构造方法
	constructor(excutor) {
		// 添加属性
		this.PromiseState = "pending";
		this.PromiseResult = "";
		this.callback = {}// 保存实例对象的this的值
		const _this = this;

		// resolve 函数
		function resolve(data) {
			if (_this.PromiseState !== "pending") return;
			// 修改对象状态 promiseState
			_this.PromiseState = "fulfilled";
			// 设置对象结果值 promiseResult
			_this.PromiseResult = data;

			setTimeout(() => {
				// 调用成功的回调函数
				_this.callback.forEach(item => {
					item.onResolevd(data);
				});
			});
		}

		// reject 函数
		function reject(data) {
			if (_this.PromiseState !== "pending") return;
			// 修改对象状态 promiseState
			_this.PromiseState = "rejected";
			// 设置对象结果值 promiseResult
			_this.PromiseResult = data;

			setTimeout(() => {
				// 调用失败的回调函数
				_this.callback.forEach(item => {
					item.onReject(data);
				});
			});
		}


		try {
			// 执行器函数同步调用
			excutor(resolve, reject);
		} catch (e) {
			reject(e);
		}

	}

	// then 方法
	then(onResolved, onRejected) {
		console _this = this;
		// 判断回调函数参数
		// 异常穿透
		if (typeof onRejected !== "function") {
			onRejected = reaason => {
				throw reaason;
			}
		}
		// 值传递
		if (typeof onResolved !== "function") {
			onRejected = value => value; //  简写:value => {return value};
		}

		return new Promise((resolve, reject) => {
			// 封装函数
			function callback(type) {
				try {
					let result = type(_this.PromiseResult);
					if (result instanceof Promise) {
						// 如果是 Promise 类型的对象
						result.then(v => {
							resolve(v);
						}, r => {
							reject(r);
						})
					} catch (e) {
						reject(e);
					}

				}
			}

			// 调用回调函数
			if (this.PromiseState === "fulfilled") {
				setTimeout(() => {
					callback(onResolved);
				});
			}
			if (this.PromiseState === "rejected") {
				setTimeout(() => {
					callback(onRejected);
				});
			}

			// 判断pending
			if (this.PromiseState === "pending") {
				// 保存回调函数
				this.callback.push = {
					onResolved: function() {
						callback(onResolved)
					},
					onRejected: function() {
						callback(onRejected)
					}
				}
			}
		});
	}

	// catch 方法
	catch (onRejected) {
		return then(undefined, onRejected);
	}

	// resolve 方法
	static resolve(value) {
		return new Promise((resolve, reject) => {
			if (value instanceof Promise) {
				value.then(v => {
					resolve(v);
				}, r => {
					reject(v);
				})
			} else {
				resolve(value);
			}
		});
	}

	// reject 方法
	static reject(reason) {
		return new Promise((resolve, reject) => {
			reject(reason);
		});
	}


	// all 方法
	static all(promises) {
		// 返回结果为promise对象
		return new Promise((resolve, reject) => {
			let count = 0;
			let arr = [];
			// 遍历
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					// 得知对象状态为成功
					count++;
					// 将当前promise对象的结果存入数组中
					arr[i] = v;
					// 每个promise对象都成功,才可以调用
					if (count === promises.length) {
						resolve(v);
					}
				}, r => {
					reject(r);
				})
			}
		});
	}

	// race 方法
	static race(promises) {
		return new Promise((resolve, reject) => {
			for (let i = 0; i < promises.length; i++) {
				promises[i].then(v => {
					// 修改返回对象的状态为 成功
					resolve(v);
				}, r => {
					// 修改返回对象的状态为 修改
					reject(r);
				})
			}
		});
	}

}

五、async与await

1. async函数

a. 返回值为promise函数
b. 返回结果由async执行的返回值决定
	i. 非promise类型的数据:成功的promise对象
	ii. promise对象
	iii. 抛出异常:失败的promise对象
c. 格式:

????在这里插入图片描述

2. await表达式

a. 右侧表达式一般为promise对象,但也可以是其他值
????i. 表达式是 promise 对象, await 返回的是 promise 成功的值·
????ii. 表达式是其它值, 直接将此值作为 await 的返回值
b. await必须写在 async 函数中, 但 async 函数中可以没有 await
????在这里插入图片描述
c. await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
???? 在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-20 22:57:21  更:2022-06-20 22:59:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:51:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码