UNPKG

code2021-l

Version:

前端自定义工具

278 lines (247 loc) 7.66 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>手写Promise</title> </head> <body> <script> const PENDING = 'pending' // 初始/未确定 const RESOLVED = 'resolved' // 成功 const REJECTED = 'rejected' // 失败 function Promise(excutor) { const self = this self.status = PENDING self.data = undefined /* { onResolved: function (){}, onRejected: function (){} } */ self.callbacks = [] // 用来保存所有待处理的成功和失败的回调函数 function resolve(value) { // 如果当前promise不是pending, 直接结束 if (self.status!==PENDING) return // 立即改状态 self.status = RESOLVED // 立即存数据 self.data = value // 异步调用待处理的成功的回调函数 setTimeout(() => { self.callbacks.forEach(callbackObj => { callbackObj.onResolved(value) }) }) } function reject(reason) { // 如果当前promise不是pending, 直接结束 if (self.status!==PENDING) return // 立即改状态 self.status = REJECTED // 立即存数据 self.data = reason // 异步调用待处理的成功的回调函数 setTimeout(() => { self.callbacks.forEach(callbackObj => { callbackObj.onRejected(reason) }) }) } try { // 立即执行执行器函数 excutor(resolve, reject) } catch (error) { reject(error) } } /* 1. 返回一个新的promise 2. 新的promise的状态由onResolved/onRejected执行的结果决定 1). 返回一个非promise ===> 成功 2). 抛出异常 ===> 失败 3). 返回一个promise ===> 与这个promise的结果一致 3. 在then中要对onResolved/onRejected进行处理: 根据当前promise的状态来操作 1). resolved: 异步调用onResolved 2). rejected: 异步调用onRejected 3). pending: 将onResolved/onRejected保存到callbacks中 */ Promise.prototype.then = function (onResolved, onRejected) { const self = this // 如果onResolved不是函数, 需要针value传递下去 onResolved = typeof onResolved === 'function' ? onResolved : value => value // 如果onRejected不是函数, 需要针reason传递下去 onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 返回一个新的promise return new Promise((resolve, reject) => { /* 调用指定的回调函数 根据执行的结果, 更新返回promise的状态 */ function handleCallback(callback) { try { const result = callback(self.data) if (result instanceof Promise) { result.then( value => {resolve(value)}, reason => {reject(reason)} ) // result.then(resolve, reject) } else { resolve(result) } } catch (error) { reject(error) } } if (self.status===RESOLVED) { setTimeout(() => { handleCallback(onResolved) }) } else if (self.status===REJECTED) { setTimeout(() => { handleCallback(onRejected) }) } else { // PENDING // 保存回调函数 self.callbacks.push({ onResolved: value => handleCallback(onResolved), onRejected: reason => handleCallback(onRejected) }) } }) } Promise.prototype.catch = function (onRejected) { return this.then(undefined, onRejected) } Promise.resolve = function (value) { // value有可能是一个promise return new Promise((resolve, reject) => { if (value instanceof Promise) { value.then(resolve, reject) } else { resolve(value) } }) } Promise.reject = function (reason) { return new Promise((resolve, reject) => { reject(reason) }) } Promise.resolveDelay = function (value, time) { return new Promise((resolve, reject) => { setTimeout(() => { if (value instanceof Promise) { value.then(resolve, reject) } else { resolve(value) } }, time) }) } Promise.rejectDelay = function (reason, time) { return new Promise((resolve, reject) => { setTimeout(() => { reject(reason) }, time) }) } Promise.race = function (promises) { return new Promise((resolve, reject) => { promises.forEach(p => p.then(resolve, reject)) }) } Promise.all = function (promises) { return new Promise((resolve, reject) => { const values = [] let resolvedCount = 0 promises.forEach((p, index) => { p.then( value => { resolvedCount++ values[index] = value if (resolvedCount===promises.length) { resolve(values) } }, reason => reject(reason) ) }) }) } </script> <script> const p1 = Promise.resolve(5) const p2 = Promise.resolve(Promise.reject(6)) const p3 = Promise.resolveDelay(7, 1000) const p4 = Promise.rejectDelay(8, 2000) // p1.then(value => console.log('p1', value)) // p2.catch(reason => console.log('p2', reason)) // p3.then(value => console.log('p3', value)) // p4.catch(reason => console.log('p4', reason)) // const p5 = Promise.race([p3, p1]) // const p5 = Promise.race([p3, p2]) // p5.then( // value => console.log('race onResolved()', value), // reason => console.log('race onRejected()', reason), // ) // const p6 = Promise.all([p1, p3]) const p6 = Promise.all([p2, p3]) p6.then( vales => console.log('all onResolved()', vales), reason => console.log('all onRejected()', reason), ) </script> <!-- <script> new Promise((resolve, reject) => { // excutor // 遍历异步任务 setTimeout(() => { // 如果成功 // resolve(1) // 如果失败 reject(2) }, 1000) // throw 3 }) .then( value => { console.log('onResolved1()', value) }, // onResolved reason => { console.log('onRejected1()', reason) throw 3 } // onRejected ) .then( value => { console.log('onResolved2()', value) }, // onResolved reason => { console.log('onRejected2()', reason) } // onRejected ) .then( value => { console.log('onResolved3()', value) } ) .catch( reason => { console.log('catch()', reason) } ) .then( value => { console.log('onResolved4()', value) }, reason => { console.log('onRejected4()', reason) } ) console.log('new Promise()之后') </script> --> </body> </html>