js-review/js/手写Promise.js

83 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 手写一个Promise
function MyPromise(fun){ // 构造函数接收一个函数
this.status = MyPromise.PENDING // 设置默认状态为待定
try {
fun.call(this, MyPromise.resolve.bind(this), MyPromise.reject.bind(this))
} catch(err){
// 如果MyPromise.prototype.then里面有err=>{}处理函数就传递给它
this.status = MyPromise.REJECT
this.result = err
}
}
// Promise 状态常量
MyPromise.PENDING = 0
MyPromise.FULFILLED = 1
MyPromise.REJECT = 2
MyPromise.resolve = function(res) {
if(this === MyPromise) return new MyPromise(resolve=>resolve(res)) // 如果是静态调用就返回一个确认的Promise
if(this.status === MyPromise.REJECT) return // Promise 的状态一旦确定就不能修改
this.status = MyPromise.FULFILLED
this.result = res
}
MyPromise.reject = function(err) {
if(this === MyPromise) return new MyPromise((resolve,reject)=>reject(err)) // 如果是静态调用就返回一个拒绝的Promise
if(this.status === MyPromise.FULFILLED) return // Promise 的状态一旦确定就不能修改
this.status = MyPromise.REJECT
this.result = err
}
MyPromise.prototype = {
then: function(res, err){
// Promise的.then要加入到任务队列不能同步执行用setTimeout模拟
var context = this // 保存的上下文
setTimeout(function(){
// 在.then中无论是onFulfilled的返回值还是onReject的返回值都会交给下一个.then的onFulfilled处理只有出现异常的时候才后交给下一个.then的onReject处理
try{
if(context.status === MyPromise.FULFILLED && res) context.result = res(context.result)
if(context.status === MyPromise.REJECT && err) {
context.result =err(context.result)
context.status = MyPromise.FULFILLED
}
}catch(err){
context.result = err
context.status = MyPromise.REJECT
}
}, 0);
return this
}
}
// 编写Promise.all([...Promies])静态方法
/**
* @description 接受一个Promise的迭代对象当全部的Promise兑现时返回一个由兑现值组成的迭代对象
* 当为空的迭代对象时也会对象一个空的迭代对象 Promise.all([]).then(res=>{console.log(res)}) res = []
*/
MyPromise.all = function (ps) {
if(typeof ps[Symbol.iterator] !== 'function') throw new Error("传递一个内容为Promise实例的可迭代对象")
var n = ps.length
var rs = []
for(var i = 0; i < n; i++) {
(function(i){
ps[i].then(res=>{
rs[i] = res
}, err=>{
// all只要出现拒绝就立马返回第一个拒绝的内容
this.status = MyPromise.REJECT;
this.result = err
})
}).call(this, i)
}
if (this.status === MyPromise.REJECT) return this
this.status = MyPromise.FULFILLED
this.result = rs
return this
}