【个人前端笔记】手写Promise
一、Promise相关问题(即面试问题)
1.Promise要解决什么问题
答:解决异步操作中出现的回调地狱问题
2.Promise有什么优点
两个优点
减少缩进,把函数里的函数变成then下面的then,即链式调用
消灭if(err),错误处理放到单独的一个函数里,如果不处理就一直往后抛,可在最后设置一个错误处理函数用于兜底
二、Promise的完整API是什么
1.Promise是一个类
JS里类是特殊的函数
类属性:length(可忽略)
类方法:all / allSettled / race / reject / resolve
对象属性:then(重要) / finally / catch
对象内部属性:state = pending / fulfilled / rejected
三、手写Promise
class Promise2 {
status:"pending" | "fulfilled" | "rejected" = "pending"
callbacks:any[][] = []
constructor(fn:fn) {
if (typeof fn !== "function") {
throw new Error("只接受函数");
}
fn(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result?:any){
if (this.status !== "pending") {
return
}
this.status = "fulfilled"
nextTick(() => {
this.callbacks.forEach(fn => {
if (typeof fn[0] === "function") {
let x
try {
x = (fn[0] as Function).call(undefined,result)
} catch (error) {
return fn[2].reject(error)
}
fn[2].resolveWith(x)
}
})
});
}
reject(reason?:any){
if (this.status !== "pending") {
return
}
this.status = "rejected"
nextTick(() => {
this.callbacks.forEach(fn => {
if (typeof fn[1] === "function") {
let x
try {
x = (fn[1] as Function).call(undefined,reason)
} catch (error) {
return fn[2].reject(error)
}
fn[2].resolveWith(x)
}
})
});
}
then(success?:Success,fail?:Fail){
let handles = []
if (typeof success === "function") {
handles[0] = success
}
if (typeof fail === "function") {
handles[1] = fail
}
handles[2] = new Promise2(() => {})
this.callbacks.push(handles)
return handles[2]
}
resolveWith(x:any){
if (this === x) {
return new TypeError("")
}else if (x instanceof Promise2) {
x.then((result) => {
this.resolve(result)
},(reason) => {
this.reject(reason)
})
}else if (x instanceof Object) {
let then
try {
then = x.then
} catch (error) {
this.reject(error)
}
if (x instanceof Function) {
try {
x.then((y:any) => {
this.resolveWith(y)
},(x:any) => {
this.reject(x)
})
} catch (error) {
this.reject(error)
}
}else{
this.resolve(x)
}
}else{
this.resolve(x)
}
}
}
export default Promise2
type fn = (resolve:Function,reject:Function) => void
type Success = ((result:any) => void) | null
type Fail = ((reason:any) => void) | null
function nextTick(fn:any) {
if (process !== undefined && typeof process.nextTick === "function") {
return process.nextTick(fn)
}else{
let count = 1
let observer = new MutationObserver(fn)
let textNode = document.createTextNode(String(count))
observer.observe(textNode)
count = (count + 1) % 2
textNode.data = String(count)
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通