赞
踩
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>手写Promise</title> </head> <body> <script> // 手写 Promise 构造函数 class MyPromise{ state = 'pending' // 状态 'pending' 'fulfilled' 'rejected' value = undefined // 当前 Promise 执行成功后的值 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方法 then(fn1, fn2){ // 在 pending 状态下,fn1 fn2会被存储到Callbacks中 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 } } // catch方法,catch 是 then的一个语法糖,简单模式 catch(fn){ return this.then(null, fn) } } // Promise 全局静态的API // resolve MyPromise.resolve = function(value){ return new MyPromise((resolve, reject)=>resolve(value)) } // reject MyPromise.reject = function(reason){ return new MyPromise((resolve, reject)=>reject(reason)) } // all 传入Promise数组,等待所有的Promise的状态都 fulfilled 之后,返回一个新的Promise,包含所有结果 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 必须在 then 里面做 ++ resolvedCount++ if(resolvedCount === length){ // 已经遍历到了最后一个 promise resolve(result) } }).catch(err=>{ reject(err) }) }) }) return p1 } // race 传入Promise数组,只要有一个Promise的状态 fulfilled 之后,返回一个新的Promise,包含该Promise结果 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 } //----------------以下是用于测试的代码------------------------------ // 初始化 & 异步调用 // const p1 = new MyPromise((resolve, reject)=>{ // 同步 // resolve(100) // reject('错误信息') // 异步 // setTimeout(()=>{ // resolve(100) // }, 1000) // }) // // then catch 链式调用 // const p11 = p1.then(data1=>{ // console.log('data1', data1) // return data1 + 1 // }) // const p12 = p11.then(data2=>{ // console.log('data2', data2) // return data2 + 2 // }) // const p13 = p12.catch(err=>console.error(err)) // // Promise基本的API .resolve .reject .all .race // const p2 = MyPromise.resolve(200) // const p3 = MyPromise.resolve(300) // const p4 = MyPromise.reject('错误信息...') // const p5 = MyPromise.all([p1, p2, p3]) // p5.then(result=>console.log('all result', result)) // const p6 = MyPromise.race([p1, p2, p3]) // p6.then(result=>console.log('race result', result)) </script> </body> </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。