一、实现Promise的基本功能
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(fn) {
this.state = PENDING
this.value = undefined
let resolve = (value) => {
if(this.state == PENDING) {
this.state = FULFILLED
this.value = value
}
}
let reject = (error) => {
if(this.state == PENDING) {
this.state = REJECTED
this.value = error
}
}
fn(resolve, reject)
}
then(onFulFilled, onRejected) {
if(this.state == FULFILLED) {
onFulFilled(this.value)
}
if(this.state == REJECTED) {
onRejected(this.value)
}
}
}
console.log('p0');
let p1 = new MyPromise((resolve,reject) => {
resolve('p1')
})
p1.then(res => {
console.log(res);
})
console.log('p2');
二、添加异常捕获
try {
fn(resolve, reject)
} catch(err) {
reject(err)
}
let p1 = new MyPromise((resolve,reject) => {
throw new Error('custom error')
})
p1.then(res => {
console.log(res);
},err => {
console.log(err);
})
三、实现Promise的异步
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(fn) {
this.state = PENDING
this.value = undefined
this.onFulCallBack = []
this.onRejCallBack = []
let resolve = (value) => {
setTimeout(() => {
if(this.state == PENDING) {
this.state = FULFILLED
this.value = value
this.onFulCallBack.forEach(cb => cb())
}
})
}
let reject = (error) => {
setTimeout(() => {
if(this.state == PENDING) {
this.state = REJECTED
this.value = error
this.onRejCallBack.forEach(cb => cb())
}
})
}
try {
fn(resolve, reject)
} catch(err) {
reject(err)
}
}
then(onFulFilled, onRejected) {
if(this.state == FULFILLED) {
onFulFilled(this.value)
}
if(this.state == REJECTED) {
onRejected(this.value)
}
if(this.state == PENDING) {
this.onFulCallBack.push(() => onFulFilled(this.value))
this.onRejCallBack.push(() => onRejected(this.value))
}
}
}
console.log('p0');
let p1 = new MyPromise((resolve,reject) => {
resolve('p1')
})
p1.then(res => {
console.log(res);
},err => {
console.log(err);
})
console.log('p2');
四、实现then中值的穿透
then(onFulFilled, onRejected) {
onFulFilled = typeof onFulFilled == 'function' ? onFulFilled : value => value
onRejected = typeof onRejected == 'function' ? onRejected : err => {throw err}
if(this.state == FULFILLED) {
onFulFilled(this.value)
}
if(this.state == REJECTED) {
onRejected(this.value)
}
if(this.state == PENDING) {
this.onFulCallBack.push(() => onFulFilled(this.value))
this.onRejCallBack.push(() => onRejected(this.value))
}
}
五、实现then的链式调用
then(onFulFilled, onRejected) {
onFulFilled = typeof onFulFilled == 'function' ? onFulFilled : value => value
onRejected = typeof onRejected == 'function' ? onRejected : err => {throw err}
let promise = new MyPromise((resolve,reject) => {
const resolvePromise = promiseRes => {
try {
var x = onFulFilled(promiseRes)
if(x instanceof MyPromise) {
x.then(resolve, reject)
}
resolve(x)
} catch(err) {
reject(err)
}
}
const rejectPromise = promiseRes => {
try {
var x = onRejected(promiseRes)
if(x instanceof MyPromise) {
x.then(resolve, reject)
}
reject(x)
} catch(err) {
reject(err)
}
}
if(this.state == FULFILLED) {
resolvePromise(this.value)
}
if(this.state == REJECTED) {
rejectPromise(this.value)
}
if(this.state == PENDING) {
this.onFulCallBack.push(() => resolvePromise(this.value))
this.onRejCallBack.push(() => rejectPromise(this.value))
}
})
return promise
}
let p1 = new MyPromise((resolve,reject) => {
resolve(123)
})
p1.then(res => {
return res
}).then(res => {
console.log(res);
})
六、catch实现
catch(onRejected) {
return this.then(null, onRejected)
}
let p = new MyPromise((resolve,reject) => {
reject('123')
})
p.catch((err) => {
console.log(err);
})
七、finally实现
finally(callback) {
let P = this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
let p = new MyPromise((resolve,reject) => {
resolve('123')
})
p.finally(() => {
console.log('finally');
})
八、Promise.all实现
static all(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
throw new Error('argument must be a Array')
}
let counter = 0
let num = promises.length
let result = []
for(let i = 0; i < num; i++) {
promises[i].then(value => {
counter++
result[i] = value
if(counter == num) {
return resolve(result)
}
}, err => {
return reject(err)
})
}
})
}
const p1 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('a')
},1000)
})
const p2 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('b')
},3000)
})
const p3 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('c')
},2000)
})
MyPromise.all([p1,p2,p3]).then(res => {
console.log(res);
})
九、Promise.resolve实现
static resolve(v) {
if(v instanceof MyPromise) {
return v
}
if(typeof v === 'object' && typeof v.then === 'function') {
return new MyPromise((res,rej) => {
v.then(res, rej)
})
}
if(!v) {
return new MyPromise(res => {
res()
})
}
return new MyPromise(res => {
res(v)
})
}
十、Promise.reject实现
static reject(v) {
return new MyPromise((res,rej) => {
rej(v)
})
}
十一、Promise.race实现
static race(promises) {
return new MyPromise((resolve, reject) => {
if(!Array.isArray(promises)) {
throw new Error('argument must be a Array')
}
for(let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject)
}
})
}
const p1 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('a')
},1000)
})
const p2 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('b')
},3000)
})
const p3 = new MyPromise((resolve) => {
setTimeout(() => {
resolve('c')
},2000)
})
MyPromise.race([p1,p2,p3]).then(res => {
console.log(res);
})
十二、完整代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(fn) {
this.state = PENDING
this.value = undefined
this.onFulCallBack = []
this.onRejCallBack = []
let resolve = (value) => {
if(value instanceof MyPromise) {
return value.then(resolve, reject)
}
setTimeout(() => {
if(this.state == PENDING) {
this.state = FULFILLED
this.value = value
this.onFulCallBack.forEach(cb => cb())
}
})
}
let reject = (error) => {
setTimeout(() => {
if(this.state == PENDING) {
this.state = REJECTED
this.value = error
this.onRejCallBack.forEach(cb => cb())
}
})
}
try {
fn(resolve, reject)
} catch(err) {
reject(err)
}
}
then(onFulFilled, onRejected) {
onFulFilled = typeof onFulFilled == 'function' ? onFulFilled : value => value
onRejected = typeof onRejected == 'function' ? onRejected : err => {throw err}
let promise = new MyPromise((resolve,reject) => {
const resolvePromise = promiseRes => {
try {
var x = onFulFilled(promiseRes)
if(x instanceof MyPromise) {
x.then(resolve, reject)
}
resolve(x)
} catch(err) {
reject(err)
}
}
const rejectPromise = promiseRes => {
try {
var x = onRejected(promiseRes)
if(x instanceof MyPromise) {
x.then(resolve, reject)
}
reject(x)
} catch(err) {
reject(err)
}
}
if(this.state == FULFILLED) {
resolvePromise(this.value)
}
if(this.state == REJECTED) {
rejectPromise(this.value)
}
if(this.state == PENDING) {
this.onFulCallBack.push(() => resolvePromise(this.value))
this.onRejCallBack.push(() => rejectPromise(this.value))
}
})
return promise
}
catch(onRejected) {
return this.then(null, onRejected)
}
finally(callback) {
let P = this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
)
}
static all(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
throw new Error('argument must be a Array')
}
let counter = 0
let num = promises.length
let result = []
for(let i = 0; i < num; i++) {
promises[i].then(value => {
counter++
result[i] = value
if(counter == num) {
return resolve(result)
}
}, err => {
return reject(err)
})
}
})
}
static resolve(v) {
if(v instanceof MyPromise) {
return v
}
if(typeof v === 'object' && typeof v.then === 'function') {
return new MyPromise((res,rej) => {
v.then(res, rej)
})
}
if(!v) {
return new MyPromise(res => {
res()
})
}
return new MyPromise(res => {
res(v)
})
}
static reject(v) {
return new MyPromise((res,rej) => {
rej(v)
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
if(!Array.isArray(promises)) {
throw new Error('argument must be a Array')
}
for(let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject)
}
})
}
}