promise实现笔记
promise的基本使用方法:
promise的三种状态: pending, fulfilled, rejected;
基本使用方法:
1、创建一个Promise执行异步任务:
1 2 3 4 5
| const p = new Promise((resolve, reject) => { setTimeout(() => { resolve("成功"); }, 1000); })
|
2、消费 Promise(then/catch)
1 2 3 4 5
| p.then(result => { console.log(result); }).catch(error => { console.error(error); })
|
3、Promise的一些其他用法:
- promise.resolve/reject
- promise.all
1
| Promise.all([promise1, promise2, ...]).then();
|
- promise.race
1
| Promise.race([promise1, promise2, ...]).then();
|
- promise.allSettled
- promise.any
简单版
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
| function MyPromise(fn){
let self = this;
let value = null; let error = null;
let status = null;
function resolve(value) { this.value = value; this.status = "fulfilled"; this.onFulfilled(self.value); } function reject(error){ this.error = error; this.status = "rejected"; this.onRejected(self.error) }
fn(resolve, reject) }
MyPromise.prototype.then = function(onFulfilled, onRejected){ this.onFulfilled = onFulfilled; this.onRejected = onRejected; }
module.exports = MyPromise;
|
但其实这个版本的实现是有问题的:
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
| const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected';
class Promise { constructor(executor){ this.status = PENDING; this.value = undefined; this.reason = undefined;
const resolve = value => { if(this.status === PENDING){ this.status = FULFILLED; this.value = value; } }
const reject = reason => { if(this.status === PENDING){ this.status = REJECTED; this.reason = reason; } } }
try { executor(resolve, reject); } catch (error) { reject(error); }
then(onFulfilled, onRejected){ setTimeout(() => { if(this.status === FULFILLED){ onFulfilled(this.value); } else if(this.status === REJECTED){ onRejected(this.reason); } }, 0); } }
const promise = new Promise((resolve, reject) => { Math.random() < 0.5 ? resolve(1) : reject(-1); }).then(res=>console.log(res),err=>console.error(err))
|
当前promise实现存在的问题:
- promise内部异步代码执行的问题:promise内部如果有异步代码执行后才resolve,then不会等待异步代码执行完毕会直接执行
- promise链式调用问题
- 值传递
因此需要新增onFulfilledCallbacks、onRejectedCallbacks维护成功、失败的任务执行队列
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
| const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECTED = 'REJECTED';
class Promise { constructor(executor){ this.state = PENDING;
this.value = undefined; this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => { if(this.state === PENDING){ this.state = FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } }
const reject = reason => { if(this.state === PENDING){ this.state = REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } }
try { executor(resolve, reject); } catch (error) { reject(error); }
then(onFulfilled, onRejected){ setTimeout(()=>{ if(this.status === PENDING){ this.onFulfilledCallbacks.push(onFulfilled); this.onRejectedCallbacks.push(onRejected); }else if(this.status === FULFILLED){ onFulfilled(this.value); }else if(this.status === REJECTED){ onRejected(this.reason); } }) } } }
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve(1), 1000); }).then(res=>console.log(res))
|
实现链式调用:promise的一大优势就是支持链式调用,具体来说就是then方法的具体实现,实际上就是返回了一个Promise:
- 保存之前promise的实例引用,即保存this
- 根据then回调函数执行的结果,决定新的Promise的状态
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
| const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECTED = 'REJECTED';
class Promise { constructor(executor){ this.state = PENDING;
this.value = undefined; this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => { if(this.state === PENDING){ this.state = FULFILLED; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } }
const reject = reason => { if(this.state === PENDING){ this.state = REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } }
try { executor(resolve, reject); } catch (error) { reject(error); }
then(onFulfilled, onRejected){ const self = this; return new Promise((resolve,reject)=>{ if(self.status === PENDING){ self.onFulfilledCallbacks.push(()=>{ try{ setTimeout(()=>{ const result = onFulfilled(self.value);
result instanceof Promise ? result.then(resolve, reject) : resolve(result); }) }catch(e){ reject(e); } }) self.onRejectedCallbacks.push(()=>{ try{ setTimeout(()=>{ const result = onRejected(self.reason); result instanceof Promise ? result.then(resolve, reject) : resolve(result); }) }catch(e){ reject(e); } }) }else if(self.status === FULFILLED){ setTimeout(()=>{ try{ const result = onFulfilled(self.value); result instanceof Promise ? result.then(resolve, reject) : resolve(result); }catch(e){ reject(e); } }) }else if(self.status === REJECTED){ setTimeout(()=>{ try{ const result = onRejected(self.reason); result instanceof Promise ? result.then(resolve, reject) : resolve(result); }catch(e){ reject(e); } }) } }) }
} }
|