/*
宏队列和微队列:
在js中执行栈在执行完同步任务后,查看执行栈是否为空,若为空去检查微任务队列是否为空,如果为空,就去执行宏任务,否则就一次性执行完所有宏任务。
执行顺序:同步任务 => 同步任务中的所有微任务 => 宏任务 => 宏任务中的所有微任务 => 下一个宏任务 => 宏任务中的所有微任务 这样形成事件循环机制。
宏任务: 定时器动画这些,例如 setTimeout,setInterval,requestAnimationFrame
微任务: js中的异步任务,例如 Promise,Object.observe,async/await
*/
(function () {
/*
Promise有三种状态:
初始态pending:创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。
成功态resolved(fulfilled):创建Promise对象时,在函数体中调用了resolve方法(即第一个参数)。
失败态rejected:创建Promise对象时,调用reject函数(即第二个参数)。
注意: 状态转换是不可逆的,不能从成功态/失败态 回到 初始态
*/
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
//Promise构造函数
//executor执行器函数
/*
Promise构造函数实现逻辑:
1. 数据需要一个初始状态,保存外部传递过来的数据,以及执行的回调函数(这个回调函数数据结构比较特殊:[{onResolved(){},onRejected(){}},{onResolved(){},onRejected(){}},.....])
2. 两个实现函数:
1)判断当前状态
2)改变初始态,转变为成功态或者失败态
3)保存外部传递的数据
4)判断是否有未执行的回调函数,成功执行onResovled,失败执行onRejected
已进入Promise函数中,使用执行器函数执行 executor(resolve, reject);
*/
/*
直接传入失败获成功的写法:
new Promise(
// 这里先会执行一段代码,再去改变状态
() => {
console.log(resolve);
},
() => {
console.log(reject);
}
);
*/
function Promise(executor) {
const _this = this;
this.status = PENDING; // 设置初始态
this.data = undefined; // 用于接收外部传来的参数
this.callbacks = []; // 每个元素的结构:onResolved(){},onRejected(){}
// 改变promise状态,成功态
function resolve(value) {
// 判断当前状态是否为初始态,如果不是初始态的话直接return,因为不能从成功态/失败态 回到 初始态
if (this.status !== PENDING) return;
_this.status = RESOLVED;
// 保存数据
_this.data = value;
// 存在未执行的回调,立即执行onResolved
if (_this.callbacks.length > 0) {
setTimeout(() => {
_this.callbacks.forEach(element => {
element.onResolved(value);
});
});
}
}
// 改变promise状态,失败态
function reject(reason) {
if (this.status !== PENDING) return;
_this.status = REJECTED;
// 保存数据
_this.data = reason;
// 存在未执行的回调,立即执行onResolved
if (_this.callbacks.length > 0) {
setTimeout(() => {
_this.callbacks.forEach(element => {
element.onRejected(reason);
});
});
}
}
// 实例一个promise是会有两个参数(resolve回调函数, reject回调函数)
// 除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
try {
// 执行器函数,会立即执行
// executor 是Promise类的一个回调函数
// executor 执行resolve还是reject取决于外部
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
/*
用到then或catch的话,Promise的写法是这样的:
const p = new Promise();
// p会执行一些事情来得到最后的状态,再根据状态执行then或者catch
p.then(() => {
console.log(resolve);
}).catch(() => {
console.log(reject);
});
*/
// then执行回调,接收成功的回调,返回一个新的promise
Promise.prototype.then = function (onResolved, onRejected) {
const _this = this;
// 判断传递过来的参数是不是函数
onResolved = typeof onResolved === 'function' ? onResolve : value => value; // 继续向下传递
onRejected =
typeof onRejected === 'function'
? onRejected
: reason => {
throw reason;
}; // 抛出异常
// 返回一个新的Promise对象
return new Promise((resolve, reject) => {
const handle = callback => {
try {
// 执行then方法传递过来的函数,并将数据带过去
const result = onResolved(_this.data);
// 这个地方应该是个递归思想,看是不是里面还有一层promise
if (result instanceof Promise) {
result.then(resolve, reject);
}
} catch (error) {
reject(error);
}
};
if (this.status === PENDING) {
// 状态为初始状态保存下来
this.callbacks.push({
onResolved(value) {
handle(value);
},
onRejected(reason) {
handle(onRejected);
},
});
} else if (this.status === REJECTED) {
// 如果回调是promise,return的promise结果就是这个promise结果
setTimeout(() => {
handle(onResolved);
});
} else {
//如果前面的promise返回的是失败的回调
setTimeout(() => {
handle(onRejected);
});
}
});
};
// catch执行回调,失败的回调
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
// 以下四个是静态方法
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
// instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
};
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
// 多个promise执行时
Promise.all = function (promises) {
let values = [];
let resolvedCount = 0;
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
resolvedCount++;
values[index] = value;
if (resolvedCount == promises.length) {
resolve(values);
}
},
reason => {
// 只要有一个失败就失败
reject(reason);
}
);
});
});
};
// 多个promise执行时
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
resolve(value);
},
reason => {
reject(reason);
}
);
});
});
};
})(window);
手写promise
最新推荐文章于 2024-11-09 09:51:19 发布