状态数据
const MyPromise = (() => {
const PENDING = 'pending', //状态变量
RESOLVED = 'resolved',
REJECTED = 'rejected',
// 符号变量外面的访问不到
promiseStatus = Symbol('PromiseStatus'), //promise的状态
promiseValue = Symbol('promiseValue'), // promise的状态数据
changeStatus = Symbol('changeStatus'); //该变promise的状态
return class MyPromise {
/**
* 改变状态的函数
* @param {*} data 状态数据
* @param {*} status 状态
*/
[changeStatus](data, status) {
//状态不可逆或者说只有在pending状态下才能推向resolved或rejected
if (this[promiseStatus] !== PENDING) {
// 如果不是pending直接结束
return;
}
// 是pending才推向后续状态
this[promiseStatus] = status;
this[promiseValue] = data;
}
/**
*
* @param {*} executor 未决阶段(pending状态)下的处理函数
*/
constructor(executor) {
//刚开始为pending
this[promiseStatus] = PENDING;
//刚开始状态数据为undefined
this[promiseValue] = undefined;
/**
* executor 为new Promise(executor)传递进来的函数
* 1.要同步执行,所在构造器函数里面要调用一次。
* 2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
*/
/**
* resolve有改变状态的能力
* 由于要改变状态和状态数据,所以要用this,
* 但是外面是直接调用resolve,this指向全局
* 所以这里用箭头函数方便点
* 然后分析reject函数也是如此,所以写个函数
* @param {*} data 状态数据
*/
const resolve = (data) => {
this[changeStatus](data, RESOLVED);
};
/**
* reject也有改变状态的能力
* @param {*} error 状态数据
*/
const reject = (error) => {
this[changeStatus](error, REJECTED);
}
/**
* 调用executor函数,执行同步代码
* 如果这里抛出错误就要推向rejected状态
* 所以要捕获错误,然后推向rejected
* */
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
}
})();
- 测试
<script src="./MyPromise.js"></script>
<script>
const pro = new MyPromise((resolve,reject)=>{
console.log('111');
// resolve('状态数据');
// setTimeout(()=>{
// resolve('状态数据');
// },3000)
throw new Error('reject')
});
console.log(pro);
</script>
后续处理
- then,catch函数
const MyPromise = (() => {
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiveValue = Symbol("PromiseValue"), //状态数据
PromiseStatus = Symbol("PromiseStatus"),
thenables = Symbol("thenables"), //thenable
catchables = Symbol("catchbles"), //catchables
changeStatus = Symbol("changeStatus"),//当前状态
settleHandle = Symbol("settleHandle"), //后续处理的通用函数
linkPromise = Symbol("linkPromise"); //创建串联的Promise
return class MyPromise {
/**
* 改变当前Promise的状态
* @param {*} newStatus
* @param {*} newValue
* @param {*} queue 执行的作业队列
*/
[changeStatus](newStatus, newValue, queue) {
if (this[PromiseStatus] !== PENDING) {
//状态无法变更
return;
}
this[PromiseStatus] = newStatus;
this[PromiveValue] = newValue;
//执行相应队列中的函数
queue.forEach(handler => handler(newValue));
}
/**
*
* @param {*} executor 未决阶段(pending状态)下的处理函数
*/
constructor(executor) {
this[PromiseStatus] = PENDING;
this[PromiveValue] = undefined;
this[thenables] = []; //后续处理函数的数组 -> resolved
this[catchables] = []; //后续处理函数的数组 -> rejected
const resolve = data => {
this[changeStatus](RESOLVED, data, this[thenables]);
}
const reject = reason => {
this[changeStatus](REJECTED, reason, this[catchables]);
}
try {
executor(resolve, reject)
}
catch (err) {
reject(err);
}
}
/**
* 处理 后续处理函数
* @param {*} handler 后续处理函数
* @param {*} immediatelyStatus 需要立即执行的状态
* @param {*} queue 作业队列
*/
[settleHandle](handler, immediatelyStatus, queue) {
if (typeof handler !== "function") {
return;
}
if (this[PromiseStatus] === immediatelyStatus) {
//直接运行
setTimeout(() => {
handler(this[PromiveValue]);
}, 0);
}
else {
queue.push(handler);
}
}
[linkPromise](thenalbe, catchable) {
function exec(data, handler, resolve, reject) {
try {
const result = handler(data); //得到当前Promise的处理结果
if (result instanceof MyPromise) {
result.then(d => {
resolve(d)
}, err => {
reject(err);
})
}
else {
resolve(result);
}
}
catch (err) {
reject(err);
}
}
return new MyPromise((resolve, reject) => {
this[settleHandle](data => {
exec(data, thenalbe, resolve, reject);
}, RESOLVED, this[thenables])
this[settleHandle](reason => {
exec(reason, catchable, resolve, reject);
}, REJECTED, this[catchables])
})
}
then(thenable, catchable) {
return this[linkPromise](thenable, catchable);
}
catch(catchable) {
return this[linkPromise](undefined, catchable);
}
static all(proms) {
return new Promise((resolve, reject) => {
const results = proms.map(p => {
const obj = {
result: undefined,
isResolved: false
}
p.then(data => {
obj.result = data;
obj.isResolved = true;
//判断是否所有的全部完成
const unResolved = results.filter(r => !r.isResolved)
if (unResolved.length === 0) {
//全部完成
resolve(results.map(r => r.result));
}
}, reason => {
reject(reason);
})
return obj;
})
})
}
static race(proms) {
return new Promise((resolve, reject) => {
proms.forEach(p => {
p.then(data => {
resolve(data);
}, err => {
reject(err);
})
})
})
}
static resolve(data) {
if (data instanceof MyPromise) {
return data;
}
else {
return new MyPromise(resolve => {
resolve(data);
})
}
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
})
}
}
})();
promise 的串联
const MyPromise = (() => {
const PENDING = 'pending', //状态变量
RESOLVED = 'resolved',
REJECTED = 'rejected',
// 符号变量外面的访问不到
promiseStatus = Symbol('PromisrStatus'), //promise的状态
promiseValue = Symbol('promiseValue'), // promise的状态数据
changeStatus = Symbol('changeStatus'), //该变promise的状态
thenables = Symbol('thenables'), //thenables作业队列
catchables = Symbol('catchables'), //catchables作业队列
settleHandle = Symbol('settleHandle'), //后续处理函数
linkPromise = Symbol('linkPromise'); //返回的promise
return class MyPromise {
/**
*
* @param {*} executor 未决阶段(pending状态)下的处理函数
*/
constructor(executor) {
//刚开始为pending
this[promiseStatus] = PENDING;
//刚开始状态数据为undefined
this[promiseValue] = undefined;
//初始化作业队列
this[thenables] = [];
this[catchables] = [];
/**
* executor 为new Promise(executor)传递进来的函数
* 1.要同步执行,所在构造器函数里面要调用一次。
* 2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
*/
/**
* resolve有改变状态的能力
* 由于要改变状态和状态数据,所以要用this,
* 但是外面是直接调用resolve,this指向全局
* 所以这里用箭头函数方便点
* 然后分析reject函数也是如此,所以写个函数
* @param {*} data 状态数据
*/
const resolve = (data) => {
this[changeStatus](data, RESOLVED, this[thenables]);
};
/**
* reject也有改变状态的能力
* @param {*} error 状态数据
*/
const reject = (error) => {
this[changeStatus](error, REJECTED, this[catchables]);
}
/**
* 调用executor函数,执行同步代码
* 如果这里抛出错误就要推向rejected状态
* 所以要捕获错误,然后推向rejected
* */
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
/**
* 改变状态的函数
* @param {*} data 状态数据
* @param {*} status 状态
* @param {*} queue 执行的作业队列
*/
[changeStatus](data, status, queue) {
//状态不可逆或者说只有在pending状态下才能推向resolved或rejected
if (this[promiseStatus] !== PENDING) {
// 如果不是pending直接结束
return;
}
// 是pending才推向后续状态
this[promiseStatus] = status;
this[promiseValue] = data;
//状态改变了 要运行作业队列
queue.forEach((handle) => handle(data));
}
/**
* 后续处理函数
* @param {*} handle 后续处理函数
* @param {*} immediatelyStatus 状态
* @param {*} queue 作业队列
*/
[settleHandle](handle, immediatelyStatus, queue) {
//handle 不是一个函数直接返回
if (typeof handle !== 'function') {
return;
}
if (this[promiseStatus] === immediatelyStatus) {
setTimeout(() => {
handle(this[promiseValue]);
})
} else {
queue.push(handle);
}
}
[linkPromise](thenable, catchable) {
return new MyPromise((resolve, reject) => {
this[settleHandle](data => {
try {
const result = thenable(data); // 返回的结果 当前promise的处理结果
resolve(result); //然后返回的promise推向resolved状态
} catch (err) {
//出了问题才推向rejected
reject(err);
}
}, RESOLVED, this[thenables]);
this[settleHandle](err => {
try {
const result = catchable(err); // 返回的结果 当前promise的处理结果
resolve(result); //然后返回的promise推向resolved状态
} catch (err) {
reject(err);
}
}, REJECTED, this[catchables]);
})
}
then(thenable, catchable) {
//调用then方法传递一个函数,或者两个函数
//如果状态是resolved那么立即执行
//如果不是resolved那么就加入到作业队列里面,等到是resolved才执行
//reject也是同样的处理
//状态是resolved那么立即执行
// if (this[promiseStatus] === RESOLVED) {
// //由于是异步执行,并且真实的效果是放在微队列里面的,而在浏览器环境中没有办法放入微队列里面,
// //所以这里采用setTimeout来模拟,放入到宏任务里面
// setTimeout(() => {
// //将数据传给他,然后外面调用的函数中的data才有值
// thenable(this[promiseValue]);
// })
// } else {
// // 不是resolved那么就加入到作业队列里面
// this[thenables].push(thenable);
// }
// this.catch(catchable);
// this[settleHandle](thenable, RESOLVED, this[thenables]);
// this.catch(catchable);
// 调用then要返回一个promise
return this[linkPromise](thenable, catchable);
}
catch (catchable) {
// this[settleHandle](catchable, REJECTED, this[catchables]);
return this[linkPromise](thenable, catchable);
}
}
})();
其它api完整的MyPromise
const MyPromise = (() => {
const PENDING = 'pending', //状态变量
RESOLVED = 'resolved',
REJECTED = 'rejected',
// 符号变量外面的访问不到
promiseStatus = Symbol('PromisrStatus'), //promise的状态
promiseValue = Symbol('promiseValue'), // promise的状态数据
changeStatus = Symbol('changeStatus'), //该变promise的状态
thenables = Symbol('thenables'), //thenables作业队列
catchables = Symbol('catchables'), //catchables作业队列
settleHandle = Symbol('settleHandle'), //后续处理函数
linkPromise = Symbol('linkPromise'); //返回的promise
return class MyPromise {
/**
*
* @param {*} executor 未决阶段(pending状态)下的处理函数
*/
constructor(executor) {
//刚开始为pending
this[promiseStatus] = PENDING;
//刚开始状态数据为undefined
this[promiseValue] = undefined;
//初始化作业队列
this[thenables] = [];
this[catchables] = [];
/**
* executor 为new Promise(executor)传递进来的函数
* 1.要同步执行,所在构造器函数里面要调用一次。
* 2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
*/
/**
* resolve有改变状态的能力
* 由于要改变状态和状态数据,所以要用this,
* 但是外面是直接调用resolve,this指向全局
* 所以这里用箭头函数方便点
* 然后分析reject函数也是如此,所以写个函数
* @param {*} data 状态数据
*/
const resolve = (data) => {
this[changeStatus](data, RESOLVED, this[thenables]);
};
/**
* reject也有改变状态的能力
* @param {*} error 状态数据
*/
const reject = (error) => {
this[changeStatus](error, REJECTED, this[catchables]);
}
/**
* 调用executor函数,执行同步代码
* 如果这里抛出错误就要推向rejected状态
* 所以要捕获错误,然后推向rejected
* */
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
/**
* 改变状态的函数
* @param {*} data 状态数据
* @param {*} status 状态
* @param {*} queue 执行的作业队列
*/
[changeStatus](data, status, queue) {
//状态不可逆或者说只有在pending状态下才能推向resolved或rejected
if (this[promiseStatus] !== PENDING) {
// 如果不是pending直接结束
return;
}
// 是pending才推向后续状态
this[promiseStatus] = status;
this[promiseValue] = data;
//状态改变了 要运行作业队列
queue.forEach((handle) => handle(data));
}
/**
* 后续处理函数
* @param {*} handle 后续处理函数
* @param {*} immediatelyStatus 状态
* @param {*} queue 作业队列
*/
[settleHandle](handle, immediatelyStatus, queue) {
//handle 不是一个函数直接返回
if (typeof handle !== 'function') {
return;
}
if (this[promiseStatus] === immediatelyStatus) {
setTimeout(() => {
handle(this[promiseValue]);
})
} else {
queue.push(handle);
}
}
[linkPromise](thenable, catchable) {
return new MyPromise((resolve, reject) => {
this[settleHandle](data => {
if (typeof thenable !== 'function') {
resolve(data);
return;
}
try {
const result = thenable(data); // 返回的结果 当前promise的处理结果
if (result instanceof MyPromise) {
//返回的是promise
result.then(d => {
resolve(d);
}, err => {
reject(err);
})
} else {
resolve(result); //然后返回的promise推向resolved状态
}
} catch (err) {
//出了问题才推向rejected
reject(err);
}
}, RESOLVED, this[thenables]);
this[settleHandle](err => {
if (typeof catchable !== 'function') {
reject(err);
return;
}
try {
const result = catchable(err); // 返回的结果 当前promise的处理结果
resolve(result); //然后返回的promise推向resolved状态
} catch (err) {
reject(err);
}
}, REJECTED, this[catchables]);
})
}
then(thenable, catchable) {
//调用then方法传递一个函数,或者两个函数
//如果状态是resolved那么立即执行
//如果不是resolved那么就加入到作业队列里面,等到是resolved才执行
//reject也是同样的处理
//状态是resolved那么立即执行
// if (this[promiseStatus] === RESOLVED) {
// //由于是异步执行,并且真实的效果是放在微队列里面的,而在浏览器环境中没有办法放入微队列里面,
// //所以这里采用setTimeout来模拟,放入到宏任务里面
// setTimeout(() => {
// //将数据传给他,然后外面调用的函数中的data才有值
// thenable(this[promiseValue]);
// })
// } else {
// // 不是resolved那么就加入到作业队列里面
// this[thenables].push(thenable);
// }
// this.catch(catchable);
// this[settleHandle](thenable, RESOLVED, this[thenables]);
// this.catch(catchable);
// 调用then要返回一个promise
return this[linkPromise](thenable, catchable);
}
catch (catchable) {
// this[settleHandle](catchable, REJECTED, this[catchables]);
return this[linkPromise](undefined, catchable);
}
static resolve(data) {
if (data instanceof MyPromise) {
return data;
}
return new MyPromise((resolve, reject) => {
resolve(data);
})
}
static reject(data) {
//reject 不返回对象
return new MyPromise((resolve, reject) => {
reject(data);
})
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = promises.map(p => {
const obj = {
result: false,
isResolved: false
};
p.then(data => {
obj.result = data;
obj.isResolved = true;
//判断是否全部完成
const isResolved = results.filters(r => !r.isResolved);
if (isResolved.length === 0) {
//全部完成
resolve(results.map(r => r.result));
}
}, err => {
// 只要有一个失败整体就失败
reject(err);
})
return obj;
})
})
}
static race(promises) {
//只要有一个resolved或者rejected那么就结束
return new MyPromise((resolve, reject) => {
promises.forEach(p => {
p.then(data => {
resolve(data);
}, err => {
reject(err);
})
})
})
}
}
})();