我们在使用Promise,为了解决异步操作,去实现同步代码的作用
平时开发时候,我们很多时候,需要等待接口返回后,去做一些处理,或者借用返回值,再调用,,如果用传统的方法,我们容易陷入回调地狱的问题,代码的可读性也不是很好
现在我们来看下Promise的原理,是如何实现的
1、Promise是一个类,执行这个类的时候,需要传入一个执行器进去,执行器立即执行
class myPromise{
// executor执行器
constructor(executor){
executor(this.resolve,this.reject)
}
resolve(){}
reject(){}
}
2、Promsise有三种状态,分别为padding、fulfilled、rejected,当状态变为fulfilled或者rejected后,状态就不可以再改变
3、resolve和reject函数是用来更改状态的 resolve = fulfilled reject = rejected
let result = new Promise((resolve,reject)=>{
resolve('成功')
reject('失败')
})
result.then((res)=>{
console.log(res) // 成功,状态变成了fulfilled
},(err)=>{
console.log(err) // 不会执行
})
现在我们来实现下resolve和reject是怎么改变状态的
const PADDING = 'padding' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
// 成功的返回值
let value = null
// 失败的返回值
let reason = null
class myPromise {
// executor执行器
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PADDING
resolve=(val)=> {
// 状态改变了之后,,就不能再改变
if (this.status !== PADDING) return
this.status = FULFILLED
value = val
}
reject=(err)=> {
// 状态改变了之后,,就不能再改变
if (this.status !== PADDING) return
this.status = REJECTED
reason = err
}
// 这里还有一个then方法
then=(successCallback, failCallback)=> {
// 状态是成功,我们就执行成功的回调
if (this.status === FULFILLED) {
successCallback(value)
}
// 状态是失败,我们就执行失败的回调
if (this.status === REJECTED) {
failCallback(value)
}
}
}
现在我们来执行下myPromise
new myPromise((resolve,reject)=>{
resolve('success')
reject('error')
}).then(res=>{
console.log(res) // success
},err=>{
console.log(err) // 不会执行
})
结果是出来了,但是如果我们的promise里面是异步怎么办呢,执行结果还是这个么,我们用setTimeout来模拟下
new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('success')
},1000)
}).then(res=>{
console.log(res) // null
},err=>{
console.log(err) // 不会执行
})
在then里面并不会返回我们想要的成功success,是什么原因呢,我们来想一下
1、then里面的回调函数,要在resolve或者reject执行完以后,去调用回调,这样是不是就可以拿到我们想要的结果,
2、我们可以把then的回调函数保存起来,在执行resolve或者reject时候,再把回调函数拿出来执行
3、我们是把回调放在一个数组中,在resolve或者reject里面,从数组中拿出来执行
const PADDING = 'padding' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
// 成功的返回值
let value = null
// 失败的返回值
let reason = null
class myPromise {
// executor执行器
constructor(executor) {
executor(this.resolve, this.reject)
}
// 开始状态-等待
status = PADDING
// 保存成功的回调函数
successCallbackList = []
// 保存失败的回调函数
failCallbackList = []
resolve=(val)=> {
// 状态改变了之后,,就不能再改变
if (this.status !== PADDING) return
this.status = FULFILLED
value = val
while(this.successCallbackList.length){
this.successCallbackList.shift()()
}
}
reject=(err)=> {
// 状态改变了之后,,就不能再改变
if (this.status !== PADDING) return
this.status = REJECTED
reason = err
while(this.failCallbackList.length){
this.failCallbackList.shift()()
}
}
// 这里还有一个then方法
then=(successCallback, failCallback)=> {
// 状态是成功,我们就执行成功的回调
if (this.status === FULFILLED) {
successCallback(value)
}else if(this.status === REJECTED){
failCallback(value)
}else{
// 状态在等待的,我们添加到数组中
this.successCallbackList.push(successCallback)
this.failCallbackList.push(failCallback)
}
}
}
现在我们来看异步的情况下,执行结果
new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve('success')
},1000)
}).then(res=>{
console.log(res) // success 1秒之后,控制台打印‘success’
})
实现了异步的情况
都知道promise是链式调用,我们可以在后面加很多个then,第一个then的值是我们promise,resolve出来的值,那我们第二个then呢,值是哪里来的?我们可以尝试下Promise,看看执行then,是什么
?返回的是一个Promise,那么我们就可以直接链接then方法
let result = new Promise((resolve)=>{
resolve()
}).then(()=>{
return '你好'
})
result.then(res=>{
console.log(res) // 你好
})
所有我们知道了,Promise的then方法,里面的返回值是一个Promise
下面我们就来实现它
then=(successCallback, failCallback)=>{
let promise = new myPromise((resolve,reject)=>{
// 状态是成功,我们就执行成功的回调
if (this.status === FULFILLED) {
let result = successCallback(value)
if(result instanceof myPromise){
result.then(resolve,reject)
}else{
resolve(result)
}
}else if(this.status === REJECTED){
let errResult = failCallback(value)
if(errResult instanceof myPromise){
errResult.then(resolve,reject)
}else{
resolve(errResult)
}
}else{
// 状态在等待的,我们添加到数组中
this.successCallbackList.push(successCallback)
this.failCallbackList.push(failCallback)
}
})
return promise
}
这样就实现了promise的链式调用
Promise的all方法
1、all
static all=(array)=>{
// 结果储存在result中
let result = []
let index = 0
return new Promise((resolve,reject)=>{
function addData (i,value){
result[i] = value
// 执行成功一项,记录下来,当所有都执行成功后,resolve出所有的值
index++
if(index===array.length){
resolve(result)
}
}
for(let i; i<array.length; i++){
let current = array[i]
// 如果是promise,把then的结果放入result中
if(current instanceof myPromise){
current.then(res=>addData(i,res),err=>reject(err))
}else{
// 不是promise,直接放入result
addData(i,current)
}
}
})
}
|