通过手写简易Promise了解基本的promise规范
核心知识点
- 初始化 & 异步调用
- 状态不可变,只能从pending转化到fulfilled或者rejected
- then & catch & 链式调用
- 实现静态api:resolve,reject,all, race
手写前期思路
- 创建promise需要用new,可以采用es6的class
- new MyPromise需要传入一个executor函数,executor函数的两个参数是resolve和reject函数,用来改变promise的状态
- promise的状态有三种,pending,fulfilled和rejected,调用resolve函数,状态从pending -> fulfilled, 调用reject,状态从pending -> rejected
- then方法和catch方法可以链式调用,但是promise的状态只能改变一次,说明返回的是一个新的promise实例,并且考虑catch是不是then的一个语法糖
- all和race的思路,参数都是数组,那么是否涉及到数组循环,然后判断的问题?
- static resolve 和 static reject,与实例方法then中调用的流程一致,并且也支持链式调用,即返回新的实例同时可以调用实例方法中then的resolve 或 reject
初始化 & 异步调用 & 状态不可变 & 链式调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| class MyPromise { state = 'pending'; value = undefined; reason = undefined; resolvedCbs = []; rejectedCbs = [];
constructor(executor) {
const resolveHandler = (value) => { if(this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.resolvedCbs.forEach(fn => fn(this.value)); } }
const rejectHandler = (reason) => { if(this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.rejectedCbs.forEach(fn => fn(this.reason)) } }
try { executor(resolveHandler, rejectHandler) } catch(err) { rejectHandler(err); } } then(onresolved, onrejected) { onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : (v) => v; onrejected = typeof onrejected === 'function' ? onrejected : (e) => e;
if(this.state === 'pending') { return new MyPromise((resolve, reject) => { this.resolvedCbs.push(() => { try { const newVal = onfulfilled(this.value); resolve(newVal); } catch(err) { reject(err); } }); this.rejectedCbs.push(() => { try { const newReason = onrejected(this.reason); reject(newReason) } catch(err) { reject(err) } }); }) }
if(this.state === 'fulfilled') { return new MyPromise((resolve, reject) => { try { const newVal = onfulfilled(this.value); resolve(newVal); } catch(err) { reject(err); } }) }
if(this.state === 'rejected') { return new MyPromise((resolve, reject) => { try { const newReason = onrejected(this.reason); reject(newReason); } catch(err) { reject(err); } }) } }
catch(onrejected) { return this.then(null, onrejected) }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const p = new MyPromise((resolve, reject) => { resolve(100); }).then(res => { console.log(res); }, err => { console.log(err); })
const p1 = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(100); }, 1000) }).then(res => { console.log(res); }, err => { console.log(err); })
|
实现静态api:resolve,reject,all, race
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class MyPromise{
static resolve(value) { return new MyPromise((resolve, reject) => resolve(value)) }
static reject(reason) { return new MyPromise((resolve, reject) => reject(reason)) }
static all(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; }
static race(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; } }
|