前言:
作者简介:我是Morning,计算机的打工人,想要翻身做主人
个人主页: Morning的主页
系列专栏: 前端面试备战
如果小编的内容有欠缺或者有改进,请指正拙著。期待与大家的交流
如果感觉博主的文章还不错的话,点赞 + 关注 + 收藏
Promise对于我自己来说,一直都处于一个仅限于只会用的状态,什么时候用,有什么好处等等差太远,根本不了解它。就只是在做项目中照葫芦画瓢的用Promise写需求。
但是在意识到JS基础重要性后,我就开始恶补JS基础,也就是这个专栏的来源。在学习之后,我与大家来分享一下我的心得
Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。
所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
而这个结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise
这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
而且状态改变过之后就不会再发生改变。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和 从pending
变为rejected
。
大白话来讲,Promise像是一个养猪场。new Promise就相当于养了一头新,这头猪猪正在成长中(pending
),这个有两种结果,要么长大了(fulfilled
),要么病死了(rejected
)。二者只有一种可能
当一个请求需要依赖上一个请求返回结果的时候,就会形成类似这样的调用结构,我看见都瑟瑟发抖,又难看,又难维护。很容易出现回调地狱(Callback Hell)
于是Promise就诞生了,用于优雅的表达异步回调
请求一(function(结果一){
请求二(function(结果二){
请求三(function(结果三){
请求四(function(结果四){
......
})
})
})
})
Promise是一个构造函数,所以调用时通过new来使用,传入函数类型的参数
resolve
函数的作用是,将Promise
对象的状态从“进行中”变为“成功”(即从 pending 变为 resolved),并将运行成功的结果作为参数传递出去;
reject
函数的作用是,将Promise
对象的状态从“进行中”变为“失败”(即从 pending 变为 rejected),并将报出的错误,作为参数传递出去。
new Promise((resolve,reject)=>{
if(长大了){
resolve()
}else{//病死了
reject()
}
})
为了更好的控制下一步执行,Promise还拥有三个实例方法 then catch finally
then方法用来控制接下来干什么,支持链式调用。养了一头新后,长大--->杀猪--->剃毛--->工厂加工猪肉--->火腿肠。then的执行必须依赖上一步的结果(比如想吃火腿肠就必须先让工厂加工),以上每一个过程都会出现两种结果,因此then又会接收两种结果(resolve对应成功 reject对应失败)。但是每一次都写reject就特别麻烦
于是诞生了catch方法,在.then()之后来.catch(),用来处理reject的情况,而且还可以监听resolve中的异常情况(监听以上任意过程的出错)
但是有时候无论是resolve还是reject(无论长大了还是病死了),都需要执行一些方法,就诞生了finally方法 。
此外为了满足更多的开发需求,就诞生了一些静态方法
all:所有都长大才执行
allSettled:所有都有结果了就执行,无论死活
any:任意一头养成就执行
race:任意一头养成或病死了就执行
reject:返回一个状态为rejected的Promise对象
resolve:
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('success');
} else {
reject('error');
}
}, 1000);
});
promise.then(result => {
console.log(result);
console.log('第一次then执行成功');
}).then(()=>{
console.log('第二次then执行成功,Promise.then()后的结果仍然是一个Promise,可以进行链式调用');
}).catch(error => {
console.log(error);
console.log('第一次then执行失败,直接跳到catch');
}).finally(()=>{
console.log('无论执行成功与否,finally都会执行');
});
两种返回结果
const PENDING ='pending'
const RESOLVED='resolved'
const REJECTED='rejected'
function myPromise(fn){
const that=this;
this.state=PENDING;
//value用来保存resolve或reject中传入的值
this.value=null
//用来保存then中的回调.因为执行完Promise,状态有可能还是等待中
that.resolvedCallback=[]
that.rejectedCallback=[]
function resolve(value){
//两个函数开始要先判断当前状态是否为等待中
if(that.state===PENDING){
that.state=RESOLVED
that.value=value
//遍历数组回调并执行
that.resolvedCallback.map(cb=>cb(that.value))
}
}
function reject(value){
//两个函数开始要先判断当前状态是否为等待中
if(that.state===PENDING){
that.state=REJECTED
that.value=value
//遍历数组回调并执行
that.resolvedCallback.map(cb=>cb(that.value))
}
}
try{
fn(resolve,reject)
}catch(e){
reject(e)
}
}
//实现then函数
myPromise.prototype.then=function(onFulfilled,OnRejected){
const that=this
//判断两个参数是否为函数类型,因为两个参数是可选参数
onFulfilled=typeof onFulfilled==='function'?onFulfilled:v=>v
OnRejected=typeof OnRejected==='function'?OnRejected:e=>{throw e}
//
if(this.state===PENDING){
this.resolvedCallback.push(onFulfilled)
this.rejectedCallback.push(onFulfilled)
}
if(this.state===RESOLVED){
onFulfilled(that.value)
}
if(this.state===REJECTED){
OnRejected(that.value)
}
}
//应用
const promise = new myPromise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('success');
} else {
reject('error');
}
}, 1000);
});
promise.then(result => {
console.log(result);
console.log('then执行成功');
});
文章灵感:阮一峰的Promise 10分钟彻底掌握手写promise及原理,难倒面试官!_哔哩哔哩_bilibili