目录
目录
1.4promise初体验(用promise做一个类似于抽奖的东西)
2.3promise对象的值——实例对象中的另外一个属性promiseResult
3.1.1Promise的构造函数:Promise(excutor){}
3.1.2Promise.prototype.then方法:(onResolved,onRejected)=>{}
3.1.3Promise.prototype.catch方法:(onRejected)=>{}
3.2.1promise.resolve方法:(value)=>{}
3.2.2promise.reject方法:(reason)=>{}
3.2.3Promise.all方法;(promises)=>{}
3.2.4Promise.race方法:(promises)=>{}
3.2.5一个promise指定多个成功/失败回调函数,调用问题
3.2.6promise.then()返回的新的promise对象由什么决定
一.promise是什么?
1.1promise理解
抽象表达:promise是一门新的技术(ES6规范),是js中进行异步编程的新解决方案(旧方案是使用回调函数)
异步编程种类:fs文件操作,AJAX,定时器
具体表达:从语法上说是一个构造函数,从功能上说promise对象用来封装一个异步操作并可以取得成功/失败的结果值
1.2使用promise的优点
指定回调函数的方式更加灵活(promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数)
<script>
let p=new Promise((resolve,reject)=>{
resolve('ok');
});
p.then(value=>{
console.log(value);
},reason=>{
console.log(reason);
})
</script>
1.4promise初体验(用promise做一个类似于抽奖的东西)
<div class="container">
<h2 class="page-header">promise初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
//生成随机数
function rand(mim,max){
return Math.ceil(Math.random()*(max-min+1)+min-1);
}
//点击按钮,两秒后显示是否中奖
//如果中奖,弹出恭喜
//若未中奖,弹出再接再厉
//获取元素对象
const btn=document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click',function(){
//promise形式实现
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{
//获取1-100的随机数
let n=rand(1,100);
//判断
if(n<=30){
resolve();
}else{
reject();
}
},1000)
});
console.log(p);
//调用then方法
p.then(()=>{
//promise状态为resolved执行下列代码
alert('恭喜你获得劳斯莱斯五万元优惠券');
},()=>{
//promise状态为rejected执行下列代码
alert('努力,继续抽,加油');
})
});
</script>
二.promise的状态以及对象的值
2.1promise的三种状态
promise的状态其实是实例对象中的一个内置属性(PromiseState),所以不能够对该属性做直接的操作
- 1.pending未定的状态
- 2.fullfilled/resolved
- 3.rejected
<script>
let p=new Promise((resolve,reject)=>{
//此时promise状态为fullfilled
//要是判断reject状态也是同理
resolve('ok');
})
//此时控制台的输出结果中可以看到promiseState的值为fullfilled
console.log(p);
</script>
2.2promise的状态的改变
只有两种情况,且一个promise对象只能改变一次,不能由成功变失败,也不能失败变成功
- pending->resolved
- pending->rejected
成功的结果数据一般称为value,失败的结果一般称为reason
2.3promise对象的值——实例对象中的另外一个属性promiseResult
该值保存了异步任务成功/失败的结果
其结果由resolve和reject执行获得
三.如何使用Promise
3.1API
3.1.1Promise的构造函数:Promise(excutor){}
- excutor函数:执行器(resolve,reject)=>{}
- resolve函数:内部定义成功时我们调用的函数value=>{}
- reject函数:内部定义失败时我们调用的函数reason=>{}
说明:executor会在promise内部立即同步调用,异步操作在执行器中执行
废话不多说,上示例代码:
<script>
let p=new Promise((resolve,reject)=>{
console.log(111);
})
console.log(222);
</script>
//输出结果为:
//111
//222
3.1.2Promise.prototype.then方法:(onResolved,onRejected)=>{}
- onResolved函数:成功的回调函数(value)=>{}
- onRejected函数:失败的回调函数(reason)=>{}
<script>
let p=new Promise((resolve,reject)=>{
let i=1;
if(i==1)
resolve("heihei");
else
reject("no");
});
p.then(value=>{
console.log(value);
},reason=>{
console.log(reason);
})
</script>
//结果为heihei
3.1.3Promise.prototype.catch方法:(onRejected)=>{}
- onRejected函数:失败的回调函数(reason)=>{}
<script>
let p=new Promise((resolve,reject)=>{
let i=2;
if(i==1)
resolve("heihei");
else
reject("no");
});
//使用catch
p.catch(reason=>{
console.log(reason);
})
</script>
//控制台输出结果为no
3.2promise的几个关键问题
3.2.1promise.resolve方法:(value)=>{}
value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
<script>
//Promise.resolve
//如果传入的参数为非promise对象,则返回的结果为成功的promise对象
let p1=Promise.resolve(521);
console.log(p1);
//此时输出的是一个promise对象,promiseresult为521,promisestate为fullfilled
//如果传入的参数为promise对象,则参数的结果决定了resolve的结果
let p2=Promise.resolve(new Promise((resolve,reject)=>{
reject('error');
}))
//此示例输出的结果为一个失败的promise对象
console.log(p2);
//因为是一个失败的promise对象,所以使用catch将其抓捕,否则报错
p2.catch(reason=>{
console.log(reason);
})
</script>
3.2.2promise.reject方法:(reason)=>{}
reason:失败的原因
说明:返回一个失败的promise对象
<script>
//和promise.resolve类似,如果其传入的参数是一个非promise对象,则它的promiseresult为该参数,如果是一个promise对象,则promiseresult为一个promise对象
let p1=Promise.reject(521);
console.log(p1);
//调用了该reject方法,即使参数是一个成功的promise对象也依旧返回一个失败的promise对象
let p2=Promise.reject(new Promise((resolve,reject)=>{
resolve('ok');
}))
console.log(p2);
</script>
3.2.3Promise.all方法;(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的promise对象,只有数组中的所有promise成功才成功
<script>
let p1=new Promise((resolve,reject)=>{
resolve('ok');
})
let p2=Promise.resolve('ok2');
let p3=Promise.resolve('ok3');
const result=Promise.all([p1,p2,p3]);
//下列输出结果是一个成功的promise对象,promiseresult的值为一个数组
console.log(result);
</script>
3.2.4Promise.race方法:(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的promise对象,第一个完成的promise的结果状态就是最终状态
<script>
//p1使用了定时器,所以不是p1第一个完成状态改变
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok');
},1000)
})
let p2=Promise.resolve('Success');
let p3=Promise.resolve('ok');
const result=Promise.race([p1,p2,p3]);
//下列的输出结果是promise对象,promiseresult为success
console.log(result);
</script>
3.2.5一个promise指定多个成功/失败回调函数,调用问题
(当promise改变对应状态时都会调用)
<script>
//promise能否执行多个回调函数
let p=new Promise((resolve,reject)=>{
resolve("相应状态的都会调用");
})
p.then((value)=>{
alert('OK');
})
p.then((value)=>{
console.log("ok");
})
</script>
3.2.6promise.then()返回的新的promise对象由什么决定
由它的回调函数的返回值决定,如果是一个promise对象,则其根据状态返回结果,如果是非promise对象,则。。
<script>
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok');
},1000);
});
p.then(value=>{
return new Promise((resolve,reject)=>{
resolve('success');
}).then(value=>{
//返回一个成功的promise对象,所以下列输出结果为:success
console.log(value);
}).then(value=>{
//上一行的返回时success字符串,所以下列输出结果是undefined
console.log(value);
})
},reason=>{
})
</script>
3.2.7promise异常穿透
<script>
//异常穿透,在最后面来一个catch则不用管中间执行过程中是否出现失败的情况
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok');
},1000);
});
p.then(value=>{
console.log(111);
}).then(value=>{
console.log(222);
}).then(value=>{
console.log(333);
}).catch(reason=>{
console.log(reason);
})
</script>
3.2.8中断promise链
<script>
//中断promise链,返回一个pending状态的promise对象即可
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('ok');
},1000);
});
p.then(value=>{
console.log(111);
return new Promise(()=>{});
}).then(value=>{
console.log(222);
}).then(value=>{
console.log(333);
}).catch(reason=>{
console.log(reason);
})
</script>
四.Promise的自定义封装
4.1promise自定义封装-实现核心逻辑
// promise的基本原理:
// 1.Promise是一个类,在执行这个类的时候会传入一个执行器,这个执行器会立即执行
// 2.Promise会有三种状态
// Pending 等待
// Fulfilled 完成
// Rejected 失败
// 3.状态一旦发生改变,那么便不可以进行对二次修改
// 4.Promise中使用resolve和reject两个函数来更改状态
// 5.then方法内部做的事情是根据状态来判断
// 如果状态是成功,调用成功回调函数
// 如果状态是失败,调用失败回调函数
//第2实现:状态与结果的管理,先定义三个常量表示状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected'
// 第1实现:新建myPromise类,传入执行器executor
class MyPromise {
// constructor: 构造器,executor: 执行器
constructor(executor) {
//executor是一个执行器, 进入会立即执行
//第1.2实现:传入resolve和reject方法
executor(this.resolve,this.reject);
}
// 储存状态的变量, 初始值是pending
status = PENDING;
// 成功后的值
value = null;
// 失败之后的原因
reason = null;
// 第4实现:resolve和reject两个函数来改变状态
// resolve和reject为什么要使用箭头函数: 因为如果直接调用的话,普通函数this指向windows或undefined,用箭头函数就可以让this指向当前实例对象
// 更改成功后的状态
resolve = (value) => {
// 第3实现:
// 只有状态是等待, 才执行状态修改
if (this.status == PENDING) {
// 状态修改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
}
}
// 更改失败后的状态
reject = (reason) => {
// 只有状态是等待, 才执行状态修改
if (this.status == PENDING) {
// 状态修改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
}
}
// 第5实现:then的简单实现
then(onFulfilled, onRejected) {
// 判断状态
if(this.status == FULFILLED) {
// 调用成功回调,并且把值返回
onFulfilled(this.value);
}else if(this.status == REJECTED) {
// 调用失败回调, 并且把原因返回
onRejected(this.reason);
}
}
}
module.exports = MyPromise;
4.2promise自定义封装-添加异步逻辑
// Promise类中加入异步逻辑
// 1.缓存成功与失败回调
// 2.then方法中的Pending的处理 (异步操作时,此时then中的状态依旧是pending)
// 3.resolve和reject中调用回调函数
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected'
class MyPromise {
// constructor: 构造器,executor: 执行器
constructor(executor) {
executor(this.resolve,this.reject);
}
status = PENDING;
value = null;
reason = null;
// 第1步实现: 缓存成功和失败回调
onFulfilledCallback = null;
onRejectedCallback = null;
// 更改状态
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 如果成功后回调存在,就进行调用
this.onFulfilledCallback && this.onFulfilledCallback(value);
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallback && this.onRejectedCallback(reason);
}
}
// 第2步实现: then方法中的Pending处理
then(onFulfilled, onRejected) {
if(this.status == FULFILLED) {
onFulfilled(this.value);
}else if(this.status == REJECTED) {
onRejected(this.reason);
}else if(this.status == PENDING) {
// 新增:因为不知道后面状态的变化情况, 所以将成功回调和失败回调存储起来
this.onFulfilledCallback = onFulfilled;
this.onRejectedCallback = onRejected;
}
}
}
module.exports = MyPromise;
4.3promise自定义封装-then的多次调用
// 实现then方法可以多次调用
// 1.将回调函数存储起来,如果是异步回调,返回的值都是需要存储起来的(新增两个数组)
// 2.回调函数存入数组当中
// 3.循环调用成功和失败回调
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected';
class MyPromise {
// constructor: 构造器,executor: 执行器
constructor(executor) {
executor(this.resolve,this.reject);
}
status = PENDING;
value = null;
reason = null;
// 第1步实现:
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
// 更改状态
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 第3步实现
// 如果成功后回调存在,就进行调用
// this.onFulfilledCallback && this.onFulfilledCallback(value);
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback && this.onRejectedCallback(reason);
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
}
then(onFulfilled, onRejected) {
if(this.status == FULFILLED) {
onFulfilled(this.value);
}else if(this.status == REJECTED) {
onRejected(this.reason);
}else if(this.status == PENDING) {
// 等待后续调用
// 第2步实现
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
}
}
module.exports = MyPromise;
4.4promise自定义封装-then的链式调用
// 实现then的链式调用
// 1. 需要一个变量,将then中返回的值保存起来
// 2. 返回一个promise对象,使得其可以继续调用
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected';
class MyPromise {
// constructor: 构造器,executor: 执行器
constructor(executor) {
executor(this.resolve,this.reject);
}
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 如果成功后回调存在,就进行调用
// this.onFulfilledCallback && this.onFulfilledCallback(value);
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback && this.onRejectedCallback(reason);
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
}
then(onFulfilled, onRejected) {
// 2.为了链式调用, 这里直接创建一个promise对象, 最后return出去
const promise2 = new MyPromise((resolve,reject) => {
if(this.status == FULFILLED) {
// 如果成功, 则需要继续返回值和调用
// 1. 将结果保存起来
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(x, resolve, reject);
}else if(this.status == REJECTED) {
onRejected(this.reason);
}else if(this.status == PENDING) {
// 等待后续调用
// 第2步实现
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
})
return promise2;
}
}
function resolvePromise(x, resolve, reject) {
if(x instanceof MyPromise) {
// 执行x, 调用then方法
x.then(resolve,reject);
}else {
// 普通值
resolve(x);
}
}
module.exports = MyPromise;
4.5promise自定义封装-then的陷入死循环
// 防止then链式调用陷入死循环(then链式调用return一个本身,造成死循环)
// 1.在then链式调用传入的值中多传一个值,用来判断是否返回本身
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected';
class MyPromise {
// constructor: 构造器,executor: 执行器
constructor(executor) {
executor(this.resolve,this.reject);
}
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 如果成功后回调存在,就进行调用
// this.onFulfilledCallback && this.onFulfilledCallback(value);
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback && this.onRejectedCallback(reason);
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
}
then(onFulfilled, onRejected) {
// 为了链式调用, 这里直接创建一个promise对象, 最后return出去
const promise2 = new MyPromise((resolve,reject) => {
if(this.status == FULFILLED) {
// 创建一个微任务, 等待promise2的初始化,否则会直接将promise2传入,但此时promise2并没有return/创建完成
queueMicrotask(() => {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
})
}else if(this.status == REJECTED) {
onRejected(this.reason);
}else if(this.status == PENDING) {
// 等待后续调用
// 第2步实现
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
})
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 多加一重判断, 是否为本身
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof MyPromise) {
// 执行x, 调用then方法
x.then(resolve,reject);
}else {
// 普通值
resolve(x);
}
}
module.exports = MyPromise;
4.6promise自定义封装-错误处理
// 参考fulfilled状态下的处理方式,对reject和pending状态进行改造
// 1.增加异步状态的链式调用
// 2.增加回调函数执行结果的判断
// 3.增加错误捕捉
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected';
class MyPromise {
// 1:错误处理机制
constructor(executor) {
try{
executor(this.resolve,this.reject);
}catch(error) {
this.reject(error);
}
}
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 如果成功后回调存在,就进行调用
// this.onFulfilledCallback && this.onFulfilledCallback(value);
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback && this.onRejectedCallback(reason);
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
}
then(onFulfilled, onRejected) {
const promise2 = new MyPromise((resolve,reject) => {
if(this.status == FULFILLED) {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
}catch(error) {
reject(error);
}
})
}else if(this.status == REJECTED) {
// 添加链式调用
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
}catch(error) {
reject(error);
}
})
onRejected(this.reason);
}else if(this.status == PENDING) {
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
})
})
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onRejected(this.reason);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
})
})
}
})
return promise2;
}
}
function resolvePromise(promise2,x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof MyPromise) {
x.then(resolve,reject);
}else {
resolve(x);
}
}
module.exports = MyPromise;
4.7promise自定义封装-then的参数可选
// 1.then中的参数变为可选
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = 'rejected';
class MyPromise {
// 1:错误处理机制
constructor(executor) {
try{
executor(this.resolve,this.reject);
}catch(error) {
this.reject(error);
}
}
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
resolve = (value) => {
if (this.status == PENDING) {
this.status = FULFILLED;
this.value = value;
// 如果成功后回调存在,就进行调用
// this.onFulfilledCallback && this.onFulfilledCallback(value);
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
}
reject = (reason) => {
if (this.status == PENDING) {
this.status = REJECTED;
this.reason = reason;
// this.onRejectedCallback && this.onRejectedCallback(reason);
while(this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
}
// then需要实现1-能多次调用(数组存值),2-链式调用(promise),3-参数可选(typeof)
then(onFulfilled, onRejected) {
// 第1步实现:then中的参数变为可选 (如果不传, 就是使用默认函数)
onFulfilled = typeof onFulfilled === 'function'? onFulfilled : value => value;
onRejected = typeof onRejected === 'funciton'? onRejected : reason => { throw reason };
const promise2 = new MyPromise((resolve,reject) => {
if(this.status == FULFILLED) {
// 链式调用中实现1-不能返回自己(将自己也传过去),2-
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
}catch(error) {
reject(error);
}
})
}else if(this.status == REJECTED) {
// 添加链式调用
queueMicrotask(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
}catch(error) {
reject(error);
}
})
}else if(this.status == PENDING) {
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
})
})
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onRejected(this.reason);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
})
})
}
})
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof MyPromise) {
x.then(resolve,reject);
}else {
resolve(x);
}
}
module.exports = MyPromise;
7624

被折叠的 条评论
为什么被折叠?



