手写 Promise
需要实现的功能
-
初始化 & 异步调用
const p1 = new Promise((resolve, reject) => {
resolve(100)
})
-
then、catch 链式调用 p.then((data) => {
return data + 1
}).then((data) => {
return data + 2
}).catch((err) => {
console.log(err)
})
p.then(fn1, fn2)
const p11 = p1.then((data) => {
return data + 1
})
const p12 = p11.then((data) => {
return data + 2
})
const p13 = p12.catch((err) => {
console.log(err)
})
-
API .resolve .reject .all .race
const p2 = Promise.resolve(200)
const p3 = Promise.reject("错误信息...")
const p4 = Promise.all([p1, p2])
const p5 = Promise.race([p1, p2])
1. 构造函数
class MyPromise {
constructor (fn) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.resolveCallbacks = [];
this.rejectCallbacks = [];
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'resolved'
this.value = value
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveHandler, rejectHandler)
} catch (err) {
rejectHandler(err)
}
}
then(fn1, fn2) {
}
catch(fn) {
return this.then(null, fn)
}
}
2. then 的链式调用
class MyPromise {
constructor (fn) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.resolveCallbacks = [];
this.rejectCallbacks = [];
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'resolved'
this.value = value
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.resolveCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveHandler, rejectHandler)
} catch (error) {
rejectHandler(err)
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (v) => v
if (this.state === 'pending') {
return new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value);
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.resolveCallbacks.push(() => {
try {
const newReason = fn2(this.reason);
reject(newReason )
} catch (err) {
reject(err)
}
})
})
}
if (this.state === 'resolved') {
return new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (error) {
reject(error)
}
})
}
if (this.state === 'rejected') {
return new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (error) {
reject(error)
}
})
}
}
catch(fn) {
return this.then(null, fn)
}
}
3. Promise-all 和 race
class MyPromise {
constructor (fn) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.resolveCallbacks = [];
this.rejectCallbacks = [];
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'resolved'
this.value = value
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.resolveCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveHandler, rejectHandler)
} catch (error) {
rejectHandler(error)
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (v) => v
if (this.state === 'pending') {
return new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value);
resolve(newValue)
} catch (error) {
reject(error)
}
})
this.resolveCallbacks.push(() => {
try {
const newReason = fn2(this.reason);
reject(newReason)
} catch (error) {
reject(error)
}
})
})
}
if (this.state === 'resolved') {
return new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (error) {
reject(error)
}
})
}
if (this.state === 'rejected') {
return new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (error) {
reject(error)
}
})
}
}
catch(fn) {
return this.then(null, fn)
}
}
MyPromise.resolve = function(value) {
return new MyPromise((resolve, reject) => resolve(value))
}
MyPromise.reject = function(reason) {
return new MyPromise((resolve, reject) => reject(reason))
}
MyPromise.all = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
const result = []
const length = promiseList.length
let resolvedCount = 0
promiseList.forEach((p) => {
p.then(data => {
result.push(data)
resolvedCount++
if (resolvedCount === length) {
resolve(result)
}
}).catch(err => {
reject(err)
})
})
})
return p1
}
MyPromise.race = function (promiseList = []) {
let resolved = false
const p1 = new MyPromise((resolve, reject) => {
promiseList.forEach(p => {
p.then(data => {
if (!resolved) {
resolve(data)
resolved = true
}
}).catch((err) => {
reject(err)
})
})
})
return p1
}
|