Promise的理解和使用
1.1Promise是什么
1、抽象表达
- Promise是一门新的技术(ES6规范)
- Promise是JS进行异步编程的新解决方案(旧方案是单纯的使用回调函数)
2、具体表达:
- 从语法上来说:Promise是一个构造函数
- 从功能上来说:Promise对象用来封装一个一步操作并可以获取其成功/失败的结果值。
1.1.1 支持链式调用,可以解决回调地域问题
1、什么是回调地狱?
- 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
2、回调地狱的缺点?
- 不便于阅读
- 不便于异常处理
3、解决方案?
- promise链式调用
初体验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap-grid.css"
rel="stylesheet"
/>
<title>基本使用</title>
</head>
<body>
<div class="container">
<h2 class="page-header">Promise 初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
</body>
<script>
//生成随机数
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
}
/**
点击按钮,2s后显示是否中奖(中奖概率30%)
*/
//获取元素对象
const btn = document.querySelector("#btn");
//绑定单击事件
btn.addEventListener("click", function () {
//定时器
// setTimeout(() => {
// //30% 1-100
// //获取从 1-100的一个随机数
// let n = rand(1, 100);
// //判断
// if (n <= 30) {
// alert('恭喜你中奖了!!');
// } else {
// alert("很遗憾,再接再厉!!");
// }
// }, 1000);
//Promise 形式实现
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
const p = new Promise((resolve, reject) => {
setTimeout(() => {
//30% 1-100
//获取从 1-100的一个随机数
let n = rand(1, 100);
//判断
if (n <= 30) {
resolve("恭喜你中奖了!,您的中奖数字为" + n); //将promise 对象的状态设置为 【成功】
} else {
reject("很遗憾,没有中奖哦!!,您的号码为" + n); //将promise 对象的状态设置为 【失败】
}
}, 1000);
});
// 调用 then方法
p.then(
(value) => {
alert(value);
},
(reason) => {
alert(reason);
}
);
});
</script>
</html>
1.1.2 Promise 的状态改变
- pending 变为resolved
- pending 变为rejected
说明: 只有这两种,且一个Promise对象 只能改变一次,无论改变成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason。
Promise的状态:
- pending 未决定的
- resolved / fulfilled 成功
- rejected 失败
Promise 对象的值
实例对象中的另一个属性(PromiseResult)
保存着对象的异步任务【成功/失败】 的结果
- resolve
- reject
Promise的基本流程
1、一个promise指定多个成功/失败回调函数,都会调用吗?
- 当promise改变为对应状态时都会调用
2、改变promise状态和指定回调函数谁先谁后?
- 都有可能,正常情况下先指定回调再改变状态,但也可以先改状态再指定回调
- 如何先改变状态再指定回调?
- 在执行器中直接用调用resolve()/reject()
- 延迟更长时间才调用then()
- 什么时候才能得到数据
- 如果先指定的回调,那么当状态发生改变时,回调函数就会调用,得到数据
- 如果先改变的状态,那么当指定回调时,回调函数就会调用,得到数据
3、promise.then() 返回的新promise的结果状态由什么决定?
- 简单表达:由then()指定的回调函数执行的结果决定
- 详细表达:
- 如果抛出异常,新的promise变为rejected,reason为抛出的异常
- 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
- 如果返回的是另一个新的promise,此promise的结果就会成为新的promise的结果。
4、promise如何串联多个操作任务?
- promise 的then()返回的一个新的Promise,可以开成then()的链式调用
- 通过then 的 链式调用串联多个同步/异步任务
5、promise 异常传透?
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 前面任何操作出了异常,都会传到最后失败的回调中处理
6、中断promise链?
- 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
- 办法:在回调函数中返回一个pendding状态的promise对象
2、自定义(手写)Promise
2.1 定义整体结构
function Promise(executor) {
//resolve函数
function resolve(data) {
}
//reject函数
function reject(data) {
}
//同步调用(执行器函数)
executor(resolve,reject);
}
//添加then 方法
Promise.prototype.then = function (onResolved,onRejected) { }
2.2 resolve() reject()函数功能实现
function Promise(executor) {
// 添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的this的值
const _this = this;
//resolve函数
function resolve(data) {
// 1、修改对象的状态(PromiseState)
_this.PromiseState = 'fulfilled';//resolved
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
}
//reject函数
function reject(data) {
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "rejected";
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
}
//同步调用(执行器函数)
executor(resolve,reject);
}
2.3 异常捕获
try {
//同步调用(执行器函数)
executor(resolve, reject);
} catch (error) {
//修改 promise对象状态为失败
reject(error);
}
2.4 确保状态只能修改一次
//resolve函数
function resolve(data) {
//判断状态
if (_this.PromiseState != "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "fulfilled"; //resolved
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
}
//reject函数
function reject(data) {
if (_this.PromiseState != "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "rejected";
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
}
2.5 实现 then() 方法执行回调
//添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
//调用回调函数
if (this.PromiseState === 'fulfilled') {
onResolved(this.PromiseResult);
}
if (this.PromiseState === 'rejected') {
onRejected(this.PromiseResult);
}
}
2.6 异步任务 then() 方法的实现
function Promise(executor) {
// 添加属性
this.PromiseState = "pending";
this.PromiseResult = null;
// 声明属性
this.callbacks = [];
//保存实例对象的this的值
const _this = this;
//resolve函数
function resolve(data) {
//判断状态
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "fulfilled"; //resolved
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
// 调用成功的回调函数
_this.callbacks.forEach(item => {
item.onResolved(data);
})
}
//reject函数
function reject(data) {
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "rejected";
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
_this.callbacks.forEach((item) => {
item.onRejected(data);
});
}
try {
//同步调用(执行器函数)
executor(resolve, reject);
} catch (error) {
//修改 promise对象状态为失败
reject(error);
}
}
//添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
//调用回调函数
if (this.PromiseState === "fulfilled") {
onResolved(this.PromiseResult);
}
if (this.PromiseState === "rejected") {
onRejected(this.PromiseResult);
}
// 判断pendding状态
if (this.PromiseState === "pending") {
// 保存回调函数
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected
});
}
};
2.7 同步任务 then() 返回结果
//添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
return new Promise((resolve, reject) => {
//调用回调函数
if (this.PromiseState === "fulfilled") {
try {
//获取回调函数的执行结果
let result = onResolved(this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
if (this.PromiseState === "rejected") {
try {
//获取回调函数的执行结果
let result = onRejected(this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 判断pendding状态
if (this.PromiseState === "pending") {
// 保存回调函数
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected,
});
}
})
};
2.8 异步任务 then() 返回结果
//添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const _this = this;
return new Promise((resolve, reject) => {
//调用回调函数
if (this.PromiseState === "fulfilled") {
try {
//获取回调函数的执行结果
let result = onResolved(this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
if (this.PromiseState === "rejected") {
try {
//获取回调函数的执行结果
let result = onRejected(this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 判断pendding状态
if (this.PromiseState === "pending") {
// 保存回调函数
this.callbacks.push({
onResolved: function () {
try {
// 执行成功回调函数
let Result = onResolved(_this.PromiseResult);
if (Result instanceof Promise) {
Result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
resolve(Result);
}
} catch (error) {
reject(error);
}
},
onRejected: function () {
try {
let Result = onRejected(_this.PromiseResult);
if (Result instanceof Promise) {
Result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
resolve(Result);
}
} catch (error) {
reject(error);
}
},
});
}
})
};
2.9 对then() 方法进行封装
//添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const _this = this;
return new Promise((resolve, reject) => {
//封装函数
function callback(type) {
try {
//获取回调函数的执行结果
let result = type(_this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
//调用回调函数
if (this.PromiseState === "fulfilled") {
callback(onResolved);
}
if (this.PromiseState === "rejected") {
callback(onRejected);
}
// 判断pendding状态
if (this.PromiseState === "pending") {
// 保存回调函数
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
});
}
})
};
2.10 catch() 方法与异常穿透
// 添加 catch 方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
在then() 方法中
// 判断回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
2.11 Promise.resolve() 封装
//添加 resolve() 方法
Promise.resolve = function (value) {
// 返回Promise对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
resolve(value);
}
});
};
2.12 Promise.reject() 封装
//添加 reject() 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
2.13 Promise.all() 封装
//添加 all() 方法
Promise.all = function (promises) {
//返回结果为promise对象
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++){
promises[i].then(value => {
// 得知对象的状态是成功
// 每个Promise对象都成功
count++;
// 将当前promise对象成功的结果存入数组中
arr[i] = value;
if (count === promises.length) {
resolve(arr);
}
}, reason => {
reject(reason);
})
}
})
}
2.14 Promise.race() 封装
//添加 race() 方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++){
promises[i].then(value => {
// 改变返回对象的状态为 【成功】
resolve(value);
}, reason => {
// 改变返回对象的状态为 【失败】
reject(reason);
})
}
});
}
2.15 回调函数 【异步执行】
// then() 方法中
//调用回调函数
if (this.PromiseState === "fulfilled") {
setTimeout(() => {
callback(onResolved);
})
}
if (this.PromiseState === "rejected") {
setTimeout(() => {
callback(onRejected);
});
}
// Promise 对象中
//resolve函数
function resolve(data) {
//判断状态
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "fulfilled"; //resolved
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
_this.callbacks.forEach((item) => {
item.onResolved(data);
});
});
}
//reject函数
function reject(data) {
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "rejected";
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
setTimeout(() => {
_this.callbacks.forEach((item) => {
item.onRejected(data);
});
});
}
2.16 class版本封装
class Promise {
//构造方法
constructor(executor) {
// 添加属性
this.PromiseState = "pending";
this.PromiseResult = null;
// 声明属性
this.callbacks = [];
//保存实例对象的this的值
const _this = this;
//resolve函数
function resolve(data) {
//判断状态
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "fulfilled"; //resolved
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
// 调用成功的回调函数
setTimeout(() => {
_this.callbacks.forEach((item) => {
item.onResolved(data);
});
});
}
//reject函数
function reject(data) {
if (_this.PromiseState !== "pending") return;
// 1、修改对象的状态(PromiseState)
_this.PromiseState = "rejected";
// 2、设置对象结果值(PromiseResult)
_this.PromiseResult = data;
setTimeout(() => {
_this.callbacks.forEach((item) => {
item.onRejected(data);
});
});
}
try {
//同步调用(执行器函数)
executor(resolve, reject);
} catch (error) {
//修改 promise对象状态为失败
reject(error);
}
}
// then() 方法封装
then(onResolved, onRejected) {
const _this = this;
// 判断回调函数参数
if (typeof onResolved !== "function") {
onResolved = (reason) => {
throw reason;
};
}
if (typeof onRejected !== "function") {
onRejected = (reason) => {
throw reason;
};
}
return new Promise((resolve, reject) => {
//封装函数
function callback(type) {
try {
//获取回调函数的执行结果
let result = type(_this.PromiseResult);
if (result instanceof Promise) {
//如果是Promise 类型的对象
result.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
//结果的对象为【成功】
resolve(result);
}
} catch (error) {
reject(error);
}
}
//调用回调函数
if (this.PromiseState === "fulfilled") {
setTimeout(() => {
callback(onResolved);
});
}
if (this.PromiseState === "rejected") {
setTimeout(() => {
callback(onRejected);
});
}
// 判断pendding状态
if (this.PromiseState === "pending") {
// 保存回调函数
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
},
});
}
});
}
//catch() 方法封装
catch(onRejected) {
return this.then(undefined, onRejected);
}
//resolve() 方法
static resolve(value) {
// 返回Promise对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} else {
resolve(value);
}
});
}
//resolve() 方法
static resolve(value) {
// 返回Promise对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
} 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(
(value) => {
// 得知对象的状态是成功
// 每个Promise对象都成功
count++;
// 将当前promise对象成功的结果存入数组中
arr[i] = value;
if (count === promises.length) {
resolve(arr);
}
},
(reason) => {
reject(reason);
}
);
}
});
}
// race() 方法
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(
(value) => {
// 改变返回对象的状态为 【成功】
resolve(value);
},
(reason) => {
// 改变返回对象的状态为 【失败】
reject(reason);
}
);
}
});
}
//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(
(value) => {
// 得知对象的状态是成功
// 每个Promise对象都成功
count++;
// 将当前promise对象成功的结果存入数组中
arr[i] = value;
if (count === promises.length) {
resolve(arr);
}
},
(reason) => {
reject(reason);
}
);
}
});
}
//race() 方法
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(
(value) => {
// 改变返回对象的状态为 【成功】
resolve(value);
},
(reason) => {
// 改变返回对象的状态为 【失败】
reject(reason);
}
);
}
});
}
}
3、async 与 await
3.1 async 函数
- 函数的返回值为Promise对象
- promise对象的结果由async函数执行的返回值决定
3.2 await 表达式
- await右侧的表达式一般为promise对象,但也可以是其它的值
- 如果表达式为promise对象,await返回的事promise 成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
3.3 注意
- await必须写在async函数中,但是async函数中可以没有await
- 如果await的promise失败了,则会抛出异常,通常需要try……catch……捕获处理