手写实现Promise详解
中间都是实现流程想直接看源码的大佬请直接点击源码查看或从参考文档中查看
Promise的基本语法
const p=new Promeise((resolve,reject)=>{
resolve() //reject()
})
p.then((res)=>{},(err)=>{}).catch((err)=>{})
按照基本语法实现
一、创建一个MyPromsie类
const p=new Promeise()
//实现
class MyPromsie{}
二、在constructor中添加基础方法
const p=new Promeise((resolve,reject)=>{
resolve() //reject()
})
p.then((res)=>{},(err)=>{}).catch((err)=>{})
///实现
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//定义函数传入的两个参数
//成功时调用
_resolve= val => {}
//失败时调用
_resolve= err> {}
//then方法 接受两个参数 一个完成时回调函数 一个拒绝时回调函数
then(onFulfilled, onRejected){}
}
三、完善方法先实现同步调用 异步调用在第四节
const p=new Promeise((resolve,reject)=>{
resolve() //reject()
})
///实现
// 定义Promise的三种状态常量
const PENDING = 'pending'; //等待
const FULFILLED = 'fulfilled'; //已完成
const REJECTED = 'rejected'; //已拒绝
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//存储完成或拒绝的值
_value = undefined
//存储状态 pending fulfilled rejected
_status = PENDING
//定义函数传入的两个参数
//完成时调用
_resolve = val => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
//状态设置为已完成
this._status = FULFILLED
//赋值已完成时传入的参数
this._value = val;
}
//拒绝时调用
_reject = err => {
//如果状态改变 就直接返回
if(this._status !== PENDING) return;
//状态设置为拒绝
this._status = REJECTED
//赋值拒绝时传入的参数
this._value = err;
}
//then方法 接受两个参数 一个完成时回调函数 一个拒绝时回调函数
then(onFulfilled, onRejected) {
let {_status, _value} = this
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
//先留到后面
break;
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
onFulfilled(_value);
break;
case REJECTED:
onRejected(_value);
break;
}
}
}
module.exports = MyPromise
- 代码运行结果
四、支持异步调用 在代码中添加队列
将then传入的函数如果状态是成功直接执行,如果还在pending放入队列中,然后resole/reject函数回调后直接调用队列中的方法。(没有使用一个变量保存回调函数,而是使用队列是因为有可能出现多个p.then方法)
!
- 完整代码
const PENDING = 'pending'; //等待
const FULFILLED = 'fulfilled'; //已完成
const REJECTED = 'rejected'; //已拒绝
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//存储完成或拒绝的值
_value = undefined
//存储状态 pending fulfilled rejected
_status = PENDING
// 失败队列,在 then 时注入,resolve 时触发
_rejectedQueues = [];
// 成功队列,在 then 时注入,resolve 时触发
_fulfilledQueues = [];
//定义函数传入的两个参数
//完成时调用
_resolve = val => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = value => {
let cb;
while ((cb = this._fulfilledQueues.shift())) {
cb(value);
}
};
//状态设置为已完成
this._status = FULFILLED
//赋值已完成时传入的参数
this._value = val;
runFulfilled(val)
}
//拒绝时调用
_reject = err => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
//状态设置为拒绝
this._status = REJECTED
//赋值拒绝时传入的参数
this._value = err;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(err);
}
}
//then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
then(onFulfilled, onRejected) {
let {_status, _value} = this
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(onFulfilled);
this._rejectedQueues.push(onRejected)
break;
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
onFulfilled(_value);
break;
case REJECTED:
onRejected(_value);
break;
}
}
}
module.exports = MyPromise
- 运行结果
五、如果promise里面返回的时另外一个Pomise对象需要等待另外一个promise返回状态后才执行当前的promise且状态取决于参数Promsie对象的状态
列:p等待了两秒以后才返回 嘎嘎嘎 的值
- 代码片段
- 完整代码
const PENDING = 'pending'; //等待
const FULFILLED = 'fulfilled'; //已完成
const REJECTED = 'rejected'; //已拒绝
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//存储完成或拒绝的值
_value = undefined
//存储状态 pending fulfilled rejected
_status = PENDING
// 失败队列,在 then 时注入,resolve 时触发
_rejectedQueues = [];
// 成功队列,在 then 时注入,resolve 时触发
_fulfilledQueues = [];
//定义函数传入的两个参数
//完成时调用
_resolve = val => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = value => {
let cb;
while ((cb = this._fulfilledQueues.shift())) {
cb(value);
}
};
// 依次执行失败队列中的函数,并清空队列
const runRejected = error => {
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(error);
}
};
/*
* 如果resolve的参数为Promise对象,
* 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
* 且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._status = FULFILLED;
this._value = value;
runFulfilled(value)
}, err => {
this._status = FULFILLED;
this._value = err;
runRejected(err);
})
} else {
this._status = FULFILLED;
this._value = val;
runFulfilled(val)
}
}
//拒绝时调用
_reject = err => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
//状态设置为拒绝
this._status = REJECTED
//赋值拒绝时传入的参数
this._value = err;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(err);
}
}
//then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
then(onFulfilled, onRejected) {
let {_status, _value} = this
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(onFulfilled);
this._rejectedQueues.push(onRejected)
break;
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
onFulfilled(_value);
break;
case REJECTED:
onRejected(_value);
break;
}
}
}
module.exports = MyPromise
- 运行结果 同列子
六、then后面还是会返回一个promise可以接then
const p=new Promeise((resolve,reject)=>{
resolve() //reject()
})
p.then((res)=>{},(err)=>{}).then((res)=>{})
- 完整代码 (代码修改then部分)
const isFunction = variable => typeof variable === 'function';
const PENDING = 'pending'; //等待
const FULFILLED = 'fulfilled'; //已完成
const REJECTED = 'rejected'; //已拒绝
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//存储完成或拒绝的值
_value = undefined
//存储状态 pending fulfilled rejected
_status = PENDING
// 失败队列,在 then 时注入,resolve 时触发
_rejectedQueues = [];
// 成功队列,在 then 时注入,resolve 时触发
_fulfilledQueues = [];
//定义函数传入的两个参数
//完成时调用
_resolve = val => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = value => {
let cb;
while ((cb = this._fulfilledQueues.shift())) {
cb(value);
}
};
// 依次执行失败队列中的函数,并清空队列
const runRejected = error => {
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(error);
}
};
/*
* 如果resolve的参数为Promise对象,
* 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
* 且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._status = FULFILLED;
this._value = value;
runFulfilled(value)
}, err => {
this._status = FULFILLED;
this._value = err;
runRejected(err);
})
} else {
this._status = FULFILLED;
this._value = val;
runFulfilled(val)
}
}
//拒绝时调用
_reject = err => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
//状态设置为拒绝
this._status = REJECTED
//赋值拒绝时传入的参数
this._value = err;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(err);
}
}
//then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
then(onFulfilled, onRejected) {
let {_status, _value} = this
// then返回的是一个Promise对象
return new MyPromise((resolve, reject) => {
// 封装一个完成时执行的函数
const fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
resolve(value);
} else {
const res = onFulfilled(value);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(resolve, reject);
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
resolve(res);
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
reject(err);
}
};
// 封装一个拒绝时执行的函数
const rejected = err => {
try {
if (!isFunction(onRejected)) {
resolve(error);
} else {
const res = onRejected(err);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(resolve, reject);
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
resolve(res);
}
}
} catch (err) {
reject(err);
}
}
// console.log('_status', _status)
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(fulfilled);
this._rejectedQueues.push(rejected)
break;
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
fulfilled(_value);
break;
case REJECTED:
rejected(_value);
break;
}
})
}
}
module.exports = MyPromise
- 运行结果
以上基本是promise的主要代码下面时参考文档中的所有Promise方法的代码
源码
/**
* 参考 文档
* https://juejin.im/post/6844903989083897870#heading-13
* https://es6.ruanyifeng.com/#docs/promise
* */
const isFunction = variable => typeof variable === 'function';
const PENDING = 'pending'; //等待
const FULFILLED = 'fulfilled'; //已完成
const REJECTED = 'rejected'; //已拒绝
class MyPromise {
constructor (handle) {
// new Promeise((resolve,reject)=>{})
try {
//定义一个handle处理行数(resolve,reject)=>{}
handle(this._resolve, this._reject)
} catch (err) {
this._reject(err)
}
}
//存储完成或拒绝的值
_value = undefined
//存储状态 pending fulfilled rejected
_status = PENDING
// 失败队列,在 then 时注入,resolve 时触发
_rejectedQueues = [];
// 成功队列,在 then 时注入,resolve 时触发
_fulfilledQueues = [];
//定义函数传入的两个参数
//完成时调用
_resolve = val => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = value => {
let cb;
while ((cb = this._fulfilledQueues.shift())) {
cb(value);
}
};
// 依次执行失败队列中的函数,并清空队列
const runRejected = error => {
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(error);
}
};
/*
* 如果resolve的参数为Promise对象,
* 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
* 且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._status = FULFILLED;
this._value = value;
runFulfilled(value)
}, err => {
this._status = FULFILLED;
this._value = err;
runRejected(err);
})
} else {
this._status = FULFILLED;
this._value = val;
runFulfilled(val)
}
}
//拒绝时调用
_reject = err => {
//如果状态改变 就直接返回
if (this._status !== PENDING) return;
//状态设置为拒绝
this._status = REJECTED
//赋值拒绝时传入的参数
this._value = err;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(err);
}
}
//then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
then(onFulfilled, onRejected) {
let {_status, _value} = this
// then返回的是一个Promise对象
return new MyPromise((resolve, reject) => {
// 封装一个完成时执行的函数
const fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
resolve(value);
} else {
const res = onFulfilled(value);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(resolve, reject);
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
resolve(res);
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
reject(err);
}
};
// 封装一个拒绝时执行的函数
const rejected = err => {
try {
if (!isFunction(onRejected)) {
resolve(error);
} else {
const res = onRejected(err);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(resolve, reject);
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
resolve(res);
}
}
} catch (err) {
reject(err);
}
}
// console.log('_status', _status)
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(fulfilled);
this._rejectedQueues.push(rejected)
break;
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
fulfilled(_value);
break;
case REJECTED:
rejected(_value);
break;
}
})
}
// catch 方法
catch(onRejected) {
return this.then(undefined, onRejected);
}
// finally 方法
finally(cb) {
return this.then(
value => MyPromise.resolve(cb()).then(() => value),
reason =>
MyPromise.resolve(cb()).then(() => {
throw reason;
})
);
}
// 静态 resolve 方法
static resolve(value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
// 静态 reject 方法
static reject(value) {
return new MyPromise((resolve, reject) => reject(value));
}
// 静态 all 方法
static all(list) {
return new MyPromise((resolve, reject) => {
// 返回值的集合
let values = [];
let count = 0;
for (let [i, p] of list.entries()) {
// 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
this.resolve(p).then(
res => {
values[i] = res;
count++;
// 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
if (count === list.length) resolve(values);
},
err => {
// 有一个被rejected时返回的MyPromise状态就变成rejected
reject(err);
}
);
}
});
}
// 添加静态race方法
static race(list) {
return new MyPromise((resolve, reject) => {
for (let p of list) {
// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
this.resolve(p).then(
res => {
resolve(res);
},
err => {
reject(err);
}
);
}
});
}
}
module.exports = MyPromise
参考文档
- juejin.im/post/684490…
- es6.ruanyifeng.com/#docs/promi…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!