Promise总共有三种状态,分别是pending,resolved,rejected。
- 状态变化是pending->resolved或者pending->rejected,且状态变化不可逆。
- pending不会触发then或者catch回调函数,resolved会触发then回调函数,rejected会触发catch回调函数。
- then正常返回resolved,里面有报错返回rejected;catch正常返回resolved,里面有报错返回rejected。
面试题
// 第一题
Promise.resolve().then(() => {
console.log(1) //返回 resolved 状态的 promise,不执行catch
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)//返回 resolved 状态的 promise
})
结果为1,3
// 第二题
Promise.resolve().then(() => {
console.log(1)
throw new Error('erro1') //原本应返回resolved状态的promise,但因为抛出异常,所以返回 rejected 状态的 promise,执行catch
}).catch(() => {
console.log(2) // 返回 resolved 状态的 promise,执行then
}).then(() => {
console.log(3) // 返回 resolved 状态的 promise
})
结果为1,2,3
// 第三题
Promise.resolve().then(() => {
console.log(1)
throw new Error('erro1') // 原本应返回resolved状态的promise,但因为抛出异常,返回 rejected 状态的 promise
}).catch(() => {
console.log(2) // 返回 resolved 状态的 promise,不执行catch
}).catch(() => {
console.log(3)
})
结果为1,2
基于以上特性手写promise如下代码:
class MyPromise {
state = 'pending' // 状态,'pending' 'fulfilled' 'rejected'
value = undefined // 成功后的值
reason = undefined // 失败后的原因
resolveCallbacks = [] // pending 状态下,存储成功的回调
rejectCallbacks = [] // pending 状态下,存储失败的回调
constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
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) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
if (this.state === 'pending') {
const p1 = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
})
return p1
}
if (this.state === 'fulfilled') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
return p1
}
if (this.state === 'rejected') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
return p1
}
}
// 就是 then 的一个语法糖,简单模式
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 = [] // 存储 promiseList 所有的结果
const length = promiseList.length
let resolvedCount = 0
promiseList.forEach(p => {
p.then(data => {
result.push(data)
// resolvedCount 必须在 then 里面做 ++
// 不能用 index
resolvedCount++
if (resolvedCount === length) {
// 已经遍历到了最后一个 promise
resolve(result)
}
}).catch(err => {
reject(err)
})
})
})
return p1
}
MyPromise.race = function (promiseList = []) {
let resolved = false // 标记
const p1 = new Promise((resolve, reject) => {
promiseList.forEach(p => {
p.then(data => {
if (!resolved) {
resolve(data)
resolved = true
}
}).catch((err) => {
reject(err)
})
})
})
return p1
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。