Promise原理

目录

resolve与reject

1.实现resolve与reject

 2.状态不可变

 3.throw

 then

1.实现then

2.定时器情况

3.链式调用

 4.微任务


resolve与reject

我们看一段代码

let p1=new Promise((resolve,reject)=>{
	resolve("成功")
	reject("失败")
})
console.log('p1',p1);

let p2=new Promise((resolve,reject)=>{
	reject('失败')
	resolve('成功')
})
console.log('p2',p2);

let p3=new Promise((resolve,reject)=>{
	throw('报错')
})
console.log('p3',p3);

在看结果:

从这里我们可以发现几个知识点:

  1.  执行resolve,Promise状态会变成fulfilled
  2. 执行reject,Promise状态会变成rejected
  3. Promise只以第一次为准,第一次成功就永久为fulfilled,第一次失败就永远状态为rejected
  4. Promise中有throw的话,就相当于第一次执行reject

1.实现resolve与reject

大家要注意一下:Promise的初始状态是pending

这里很重要的一步是resolvereject的绑定this,为什么要绑定this呢?这是为了resolverejectthis指向永远指向当前的MyPromise实例,防止随着函数执行环境的改变而改变,我们接下来看代码:

class MyPromise{
	// 创建构造方法
	constructor(executor){
		//初始化值
		this.initValue()
		// 初始化this指向
		this.initBind()
		// 执行传进来的函数
		executor(this.resolve,this.reject)
	}

	initBind(){
		// 初始化this
		this.resolve=this.resolve.bind(this)
		this.reject=this.reject.bind(this)
	}
	initValue(){
		// 初始化值
		this.PromiseResult=null; //终值
		this.PromiseState='pedding' //状态
	}

	resolve(value){
		// 如果执行resolve,状态为fulfilled
		this.PromiseState='fulfilled'
		// 终值为传进来的值
		this.PromiseResult=value
	}

	reject(reason){
		// 如果执行reject,状态变为rejected
		this.PromiseState='rejected'
		// 终值为传进来的reason
		this.PromiseResult=reason
	}
}

const t1=new MyPromise((resolve,reject)=>{
	resolve('成功')
})
console.log(t1);
const t2=new MyPromise((resolve,reject)=>{
	reject('失败')
})
console.log(t2);

这段代码传出的结果为:

t1:

t2: 

 2.状态不可变

上面说的由第一次状态决定状态其实是不正确的,如下:

const t3=new MyPromise((resolve,reject)=>{
	resolve("成功")
	reject("失败")
})

结果按我们的概念来说返回的应该为resolve('成功'),但结果为:

 这是个什么原理呢?

因为Promise有三种状态:

  1. pending:等待中,是初始状态
  2. fulfilled:成功状态
  3. rejected:失败状态

一旦状态从pending变为fulfilled或者rejected时,那么Promise实例的状态就定死了

其实实现起来也很容易,在resolve与reject上加上判断条件即可:

resolve(value){
		// 如果执行resolve,状态为fulfilled
		// state是不可变的
		if(this.PromiseState !== 'pending') return
		this.PromiseState='fulfilled'
		// 终值为传进来的值
		this.PromiseResult=value
	}

	reject(reason){
		// state是不可变的
		if(this.PromiseState !== 'pending') return
		// 如果执行reject,状态变为rejected
		this.PromiseState='rejected'
		// 终值为传进来的reason
		this.PromiseResult=reason
	}

再来看看效果:

t3:

 3.throw

Promise中有throw,就相当执行了reject,这个时候就可以使用try catch

	// 创建构造方法
	constructor(executor){
		//初始化值
		this.initValue()
		// 初始化this指向
		this.initBind()
		try{
		// 执行传进来的函数
			executor(this.resolve,this.reject)
		}catch(e){
			// 有错误直接执行reject
			this.reject(e)
		}
	}
const t4=new MyPromise((resolve,reject)=>{
	throw("失败")
})
console.log(t4);

结果为:

 then

then方法是Promise接收回调内容的

const p1=new Promise((resolve,reject)=>{
	resolve("成功")
}).then(res=>console.log(res),err=>console.log(err))
// 马上输出成功
const p2=new Promise((resolve,reject)=>{
	setTimeout(()=>{
		reject("失败")
	},1000)
}).then(res=>console.log(res),err=>console.log(err))
// 1秒后输出失败
const p3=new Promise((resolve,reject)=>{
	resolve(100)
}).then(res => 2 * res ,err => console.log(err))
  .then(res=>console.log(res),err=>console.log(err))
//   链式调用 输出200

可以总结几个知识点:

  1. then接收两个回调,一个是成功回调,一个是失败回调
  2. 当Promise状态为fulfilled执行成功回调,rejected执行失败回调
  3. 如resolve或rejected在定时器里,则定时器结束后再执行then
  4. then支持链式调用,下一次then执行受上一次then返回值的影响

1.实现then

then(onFulfilled,onRejected){
		// /接收回调onFulfilled,onRejected

		// 参数校验,确保为函数
		onFulfilled=typeof onFulfilled === 'function' ? onFulfilled :val => val
		onRejected=typeof onRejected === 'function' ? onRejected :reason => {throw reason}
		if(this.PromiseState === 'fulfilled'){
			// 如果当前为成功状态,执行第一个回调
			onFulfilled(this.PromiseResult)
		}else if(this.PromiseState === 'rejected'){
			// 如果当前为失败状态,执行第二个回调
			onRejected(this.PromiseResult)
		}
	}
const test = new MyPromise((resolve, reject) => {
    resolve('成功')
}).then(res => console.log(res), err => console.log(err))
// 输出 成功

2.定时器情况

上面我们已经基本实现了then的基本功能,那定时器呢

还是那个代码,怎么才能保证,1秒后才执行then里的失败回调呢?

这里的核心点在这1秒时间内,我们可以先把then里的两个回调保存起来,到1秒之后再执行resolve或者reject,最后再进行判断状态

	initValue() {
		// 初始化值
		this.PromiseResult = null; //终值
		this.PromiseState = 'pending' //状态
		this.onFulfilledCallbacks = [] //保存成功回调
		this.onRejectedCallbacks = []
	}

	resolve(value) {
		// 如果执行resolve,状态为fulfilled
		// state是不可变的
		if (this.PromiseState !== 'pending') return
		this.PromiseState = 'fulfilled'
		// 终值为传进来的值
		this.PromiseResult = value
		// 执行保存成功的回调
		while (this.onFulfilledCallbacks.length) {
			this.onFulfilledCallbacks.shift()(this.PromiseResult)
		}
	}

	reject(reason) {
		// state是不可变的
		if (this.PromiseState !== 'pending') return
		// 如果执行reject,状态变为rejected
		this.PromiseState = 'rejected'
		// 终值为传进来的reason
		this.PromiseResult = reason
		// 执行保存失败的回调
		while (this.onRejectedCallbacks.length) {
			this.onRejectedCallbacks.shift()(this.PromiseResult)
		}
	}
	then(onFulfilled, onRejected) {
		// /接收回调onFulfilled,onRejected

		// 参数校验,确保为函数
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
		onRejected = typeof onRejected === 'function' ? onRejected : reason => {
			throw reason
		}
		if (this.PromiseState === 'fulfilled') {
			// 如果当前为成功状态,执行第一个回调
			onFulfilled(this.PromiseResult)
		} else if (this.PromiseState === 'rejected') {
			// 如果当前为失败状态,执行第二个回调
			onRejected(this.PromiseResult)
		} else if (this.PromiseState === 'pending') {
			// 如果状态为等待,暂时保存两个回调
			this.onFulfilledCallbacks.push(onFulfilled.bind(this))
			this.onRejectedCallbacks.push(onRejected.bind(this))
		}
	}

我们看看执行结果:

 const t2=new Promise((resolve,reject)=>{
setTimeout(() => {
	resolve("成功")
	// reject("失败")
}, 1000)
}).then(res=>console.log(res),err=>console.log(err))

3.链式调用

then支持链式调用,下一次then执行受上一次then返回值的影响,给大家举个例子:

const t3 = new Promise((resolve, reject) => {
		resolve(100)
}).then(res => 2 * res, err => console.log(err))
	.then(res => console.log(res), err => console.log(err))

const t4=new Promise((resolve,reject)=>{
	resolve(100)
}).then(res=>new Promise((resolve,reject)=>resolve(3 * res)),err => console.log(err)).then(res=> console.log(res),err=> console.log(err))

结果为200,300

从什么的内容我们可以获取几个知识点

  1. then方法本身会返回一个新的Promise对象
  2. 如果返回值是promise对象,返回值为成功,新promise就是成功
  3. 如果返回值是promise对象,返回值为失败,新promise就是失败
  4. 如果返回值为非promise对象,新promise对象就是成功,值为此返回值

咱们知道then是Promise上的方法,那如何实现then完还能再then呢?很简单,then执行后返回一个Promise对象就行了,就能保证then完还能继续执行then,代码实现:

	then(onFulfilled, onRejected) {
		// /接收回调onFulfilled,onRejected

		// 参数校验,确保为函数
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
		onRejected = typeof onRejected === 'function' ? onRejected : reason => {
			throw reason
		}

		var thenPromise=new MyPromise((resolve,reject)=>{
			const resolvePromise=cb =>{
				try{
					const x =cb(this.PromiseResult)
					if(x === thenPromise){
						// 不能返回自身
						throw new Error('不能返回自身。。。')
					}
					if(x instanceof MyPromise){
						 // 如果返回值是Promise
						x.then(resolve,reject)
					}else{
						// 非Promise就直接成功
						resolve(x)
					}
				}catch(err){
					// 处理报错
					reject(err)
					throw new Error(er)
				}
			}
			if (this.PromiseState === 'fulfilled') {
				// 如果当前为成功状态,执行第一个回调
				onFulfilled(this.PromiseResult)
				resolvePromise(onFulfilled)
			} else if (this.PromiseState === 'rejected') {
				// 如果当前为失败状态,执行第二个回调
				onRejected(this.PromiseResult)
				resolvePromise(onRejected)
			} else if (this.PromiseState === 'pending') {
				// 如果状态为等待,暂时保存两个回调
				this.onFulfilledCallbacks.push(onFulfilled.bind(this))
				this.onRejectedCallbacks.push(onRejected.bind(this))
				this.onFulfilledCallbacks.push(resolvePromise.bind(this,onFulfilled))
				this.onRejectedCallbacks,push(resolvePromise.bind(this,onRejected))
			}
		})

		// 返回这个包装的Promise
		return thenPromise
	}

调用代码:

const t3 = new Promise((resolve, reject) => {
		resolve(100)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log('成功', res), err => console.log('失败', err))

const t4=new Promise((resolve,reject)=>{
	resolve(100)
}).then(res => new Promise((resolve, reject) => reject(2 * res)), err => new Promise((resolve, reject) => resolve(3 * err))).then(res=> console.log('成功',res),err=> console.log('失败',err))

结果为:

 4.微任务

看过js执行机制的兄弟都知道,then方法是微任务,啥叫微任务呢?其实不知道也不要紧,我通过下面例子让你知道:

const t=new Promise((resolve,reject)=>{
	resolve(1)
}).then(res=>console.log(res),err=>console.log(err))
console.log(2);
输出顺序为2,1

为啥不是 1 2 呢?因为then是个微任务啊。。。同样,我们也要给我们的MyPromise加上这个特性(我这里使用定时器,大家别介意哈)

只需要让resolvePromise函数异步执行就可以了

const resolvePromise = cb => {
				setTimeout(() => {
					try {
						const x = cb(this.PromiseResult)
						if (x === thenPromise) {
							// 不能返回自身
							throw new Error('不能返回自身。。。')
						}
						if (x instanceof MyPromise) {
							// 如果返回值是Promise
							x.then(resolve, reject)
						} else {
							// 非Promise就直接成功
							resolve(x)
						}
					} catch (err) {
						// 处理报错
						reject(err)
						throw new Error(er)
					}
				})

			}

效果为:

const t=new MyPromise((resolve,reject)=>{
	resolve(1)
}).then(res=>console.log(res),err=>console.log(err))
console.log(2);
//顺序为2 1

Promise还有着其他的方法,我就不细谈了哈

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值