分析原生Promise
先来看下Promise
的调用方式:
new Promise((resolve, reject) => {
console.log('promise--开始执行同步代码')
setTimeout(()=>{
resolve('promise--00--init')
})
}).then((res)=> {
console.log('promise--01--succ', res);
return Promise.resolve(24)
}, (err)=> {
console.log('promise--01--failed', err);
}).then((res)=> {
console.log('promise--02--succ', res);
},(err)=> {
console.log('promise--02--failed', err);
}).catch(err => {
console.log('mypromise--03--catch', err);
}).then((res)=> {
console.log('promise--04--succ', res);
},(err)=> {
console.log('promise--04--failed', err);
})
// 下面是输出:
// promise--开始执行同步代码
// index.html:44 promise--01--succ promise--00--init
// index.html:49 promise--02--succ 24
// index.html:55 promise--04--succ undefined
通过以上的代码可以分析:
1.new Promise()
在执行完内部代码后(不管里面的异步代码如何执行),会立即返回一个promise对象。
- promise对象的原型上面必须存在一个
then
方法才能执行promise.then()
,否则会报错。 - 对象方法的执行是同步的, 所以
promise.then()
会立即执行完毕,then
方法返回一个promise
对象,所以promise
对象的then
方法可以链式调用。 -
then
方法会立即执行,但是它里面携带的两个参数不会立即执行,而是被保存在某个队列里面。这两个参数会等待某个时刻promise
发出调用的指令才会执行。
看自己实现的源代码吧
const STATUS = {
WAITING: 'waiting',
RESOLVE: 'resolve',
REJECT: 'reject'
}
// 开始执行函数
function handlePublish(data) {
const {status} = this
if(!this.resolveCallbacks.length ) return
let resolveFun = this.resolveCallbacks.splice(0, 1)[0]
let rejectFun = this.rejectCallbacks.splice(0, 1)[0]
try {
let currentFun = status === STATUS.RESOLVE ? resolveFun: rejectFun
let resData = currentFun && currentFun.call(this, data)
// 检测返回值是否是MyPromise的实例,重新定义原始函数参数
if(resData instanceof MyPromise) {
let that = this
return resData.then(res => {
that.originCallback = (resolve, reject= null) => resolve(res)
publish.call(this)
}, err => {
that.originCallback = (resolve=null, reject) => reject(err)
publish.call(this)
})
} else {
this.originCallback = (resolve, reject= null) => resolve(resData)
}
} catch (error) { // 重新定义原始函数参数
this.originCallback = (resolve=null, reject) => reject(error)
}
publish.call(this)
}
// 发布消息
function publish() {
this.status = STATUS.WAITING
this._publish()
}
function MyPromise(originCallback = null) {
// 最原始传入的函数
this.originCallback = originCallback
// promise对象状态
this.status = STATUS.WAITING
// 成功的回调函数数组
this.resolveCallbacks = []
// 失败的回调函数数组
this.rejectCallbacks = []
// 执行成功的函数
this.resolveFun = function(res) {
if(this.status !== STATUS.WAITING) return
this.status = STATUS.RESOLVE
setTimeout(()=> {
handlePublish.call(this, res)
})
}
// 执行失败的函数
this.rejectFun = function(err) {
if(this.status !== STATUS.WAITING) return
this.status = STATUS.REJECT
setTimeout(()=> {
handlePublish.call(this, err)
})
}
if(this.originCallback && typeof originCallback === 'function') this._publish()
}
// 执行初始函数参数
MyPromise.prototype._publish = function() {
try {
this.originCallback(this.resolveFun.bind(this), this.rejectFun.bind(this))
} catch (err) {
this.rejectFun(err)
}
}
MyPromise.prototype.then = function(successFun = null, errorFun = null) {
successFun = typeof successFun === 'function' ? successFun: resolve => resolve
errorFun = typeof errorFun === 'function' ? errorFun: resolve => {throw resolve}
this.resolveCallbacks.push(successFun)
this.rejectCallbacks.push(errorFun)
return this
}
MyPromise.prototype.catch = function(errorFun = null) {
return this.then(null, errorFun)
}
MyPromise.resolve = function resolve(data) {
if (data instanceof MyPromise) {
return data.then(res => res)
} else {
return new MyPromise(resolve => {
resolve(data)
})
}
}
MyPromise.reject = function reject(data) {
if (data instanceof MyPromise) {
return data.then(res => res, newerr => {
throw newerr
})
} else {
return new MyPromise((resolve = null,reject) => {
reject(data)
})
}
}
MyPromise.all = function all(proArr = []) {
let resArr = []
return new MyPromise((resolve, reject) => {
proArr.forEach(pro => {
pro.then(res => {
resArr.push(res)
if(resArr.length === proArr.length) {
return resolve(resArr)
}
}, err => {
reject(err)
})
})
})
}
MyPromise.race = function all(proArr = []) {
return new MyPromise((resolve, reject) => {
proArr.forEach(pro => {
pro.then(res => {
return resolve(res)
}, err => {
return reject(err)
})
})
})
}
export default MyPromise
测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实现prmise</title>
<script src="../../build/promise.js"></script>
</head>
<body>
<script>
// 测试链式调用
setTimeout(() => {
console.log('-------------------------------测试链式调用-----------------------------');
let p = new myPromise((resolve, reject) => {
console.log('mypromise--开始执行同步代码')
setTimeout(()=>{
resolve('mypromise--00--init')
})
}).then((res)=> {
console.log('mypromise--01--succ', res);
return myPromise.resolve(12)
}, (err)=> {
console.log('mypromise--01--failed', err);
}).then((res)=> {
console.log('mypromise--02--succ', res);
}, (err)=> {
console.log('mypromise--02--failed', err);
}).catch(err => {
console.log('mypromise--03--catch', err);
}).then((res)=> {
console.log('mypromise--04--succ', res);
},(err)=> {
console.log('mypromise--04--failed', err);
})
setTimeout(()=> {
console.log('*************************************');
let p2 = new Promise((resolve, reject) => {
console.log('promise--开始执行同步代码')
setTimeout(()=>{
resolve('promise--00--init')
})
}).then((res)=> {
console.log('promise--01--succ', res);
return Promise.resolve(24)
}, (err)=> {
console.log('promise--01--failed', err);
}).then((res)=> {
console.log('promise--02--succ', res);
},(err)=> {
console.log('promise--02--failed', err);
}).catch(err => {
console.log('mypromise--03--catch', err);
}).then((res)=> {
console.log('promise--04--succ', res);
},(err)=> {
console.log('promise--04--failed', err);
})
}, 30)
}, 0)
// 测试Promise的静态方法resolve或者reject
setTimeout(()=>{
console.log('----------------测试Promise的静态方法resolve或者reject-------------------');
myPromise.resolve(myPromise.reject(123)).then(res => {
console.log('myPromise------success', res);
}, err => {
console.log('myPromise------failed', err);
})
setTimeout(() => {
console.log('*************************************');
Promise.resolve(Promise.reject(123)).then(res => {
console.log('Promise------success', res);
}, err => {
console.log('Promise------failed', err);
})
}, 30)
}, 100)
// 测试Promise的静态方法all
setTimeout(()=>{
console.log('-----------------------测试Promise的静态方法all-------------------------');
myPromise.all([myPromise.resolve(123), myPromise.resolve(456)]).then(res => {
console.log('myPromise------success', res);
}, err => {
console.log('myPromise------failed', err);
})
setTimeout(() => {
console.log('*************************************');
Promise.all([Promise.resolve(123), Promise.resolve(456)]).then(res => {
console.log('Promise------success', res);
}, err => {
console.log('Promise------failed', err);
})
}, 30)
}, 200)
// 测试Promise的静态方法race
setTimeout(()=>{
console.log('-----------------------测试Promise的静态方法race-------------------------');
myPromise.race([myPromise.reject(123), myPromise.reject(456)]).then(res => {
console.log('myPromise------success', res);
}, err => {
console.log('myPromise------failed', err);
})
setTimeout(() => {
console.log('*************************************');
Promise.race([Promise.reject
(123), Promise.reject(456)]).then(res => {
console.log('Promise------success', res);
}, err => {
console.log('Promise------failed', err);
})
}, 30)
}, 300)
</script>
</body>
</html>