1、引入Promise
- 字面意义”承诺”,将来的某个时间进行兑现
- 主要解决地域回调问题
- Promise是异步的一种解决方案
- Promise是一个构造函数,有属性和方法;通过new实例化使用
2、Promise相关特点
Promise – ( 兑现承诺 )
- 要么成功要不失败,只能有一个结果
excutor – ( 执行器函数 )
当 new Promise(excutor) 的时候,excutor函数自动执行;(
同步执行
)excutor函数有两个参数:resolve – 成功的回调函数 和 reject – 失败的回调函数
then – ( 链式调用 )
then是异步调用的:
内部是利用微任务 或 宏任务处理
每次调用then都返回一个新的Promise对象
(继续下次链式调用)then(call1,call2)方法里两个回调函数,即成功的回调和失败回调
then(call1,call2)本次执行call2方法,如果继续调用then方法
- 本次call2执行结果为”成功”,下次then就执行call1
- 本次call2执行结果为”失败”,下次then就执行call2
穿透作用:
如果上个then函数没,没有对应函数的处理,就会在下一个then的回调对应执行
- let promise = new Promise((resolve, reject) => { resolve(“new Promise”) });
- promise.then()
- .then((value) => {
- console.log(“—“, value); //new Promise
- }, (reason) => {
- console.log(“—“, reason);
- })
catch – ( 链式调用 )
内部的执行原理:then(null,callBacks)
不影响继续调用 then 方法
会受到前面then方法的第二个回调函数
拦截
3、源码解析
步骤分析
- 1、new MyPromise() 时自动触发executor函数(同步执行)
- 2、调用then方法时,收集成功或失败函数(前提executor内异步执行)
- 3、手动调用resolve或reject时,异步循环执行上一步收集的函数
- 4、对上一步每次函数的执行结果放到resolvePromise函数中做处理
源码实现
const PENDING = "PENDING",
FULFILLED = "FULFILLED",
REJECTED = "REJECTED";
class MyPromise {
//executor
///1、自执行函数,new MyPromise时立刻执行
///2、包含两个参数:resolve和reject函数
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
// 分别盛放所有的成功或失败的回调函数
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 不放到原型上:resolve和reject
// 由于每次new的时候都需要创建自己的resolve和reject方法
const resolve = (value) => {
if (this.status == PENDING) {//状态只能被修改一次
this.value = value;
this.status = FULFILLED;
//发布:迭代执行成功函数
this.onFulfilledCallbacks.forEach(fn => fn());
}
}
const reject = (value) => {
if (this.status == PENDING) {//状态只能被修改一次
this.reason = value;
this.status = REJECTED;
//发布:迭代执行失败函数
this.onRejectedCallbacks.forEach(fn => fn());
}
}
// 实例化时:executor函数内异常捕获处理 - 例如:throw new Error()
try {
// executor:此方法同步执行
executor(resolve, reject);
} catch (error) {
reject(error)
}
}
// 每个then都返回一个新的promie对象,进行链式调用
then(onFulfilled, onRejected) {
// 解决穿透问题:如果onFulfilled或onRejected为空,默认给一个函数
// 例如:promise2.then().then().then((resolve,reject)=>{...})
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason };
// 创建一个promise对象作为返回值
let promise2 = new MyPromise((resolve, reject) => {
// 以下代码使用setTimeout包裹:
/// 1、使用setTimeout(宏任务)的处理方式,确保可以取到当前promise2的对象
/// 2、源码中用的是微任务的处理方式
/// 3、保障了多次then的链式调用,等待上次执行结束后才能执行下次( 事件循环机制 )
// 下列代码res的值作为resolve和reject返回值
/// 1、可能为普通值
/// 2、可能为primise对象
/// 3、使用resolvePromise方法进行处理
// 同步代码执行executor时,且状态为FULFILLED
if (this.status == FULFILLED) {
setTimeout(() => {
// 处理结果中抛出异常的情况,如:throw new Error()
try {
let res = onFulfilled(this.value)
// 处理返回值的函数
resolvePromise(promise2, res, resolve, reject)
} catch (error) {
reject(error);
}
}, 0);//具体延迟执行的时间>=4ms;
}
// 同步代码执行executor时,且状态为REJECTED
if (this.status == REJECTED) {
setTimeout(() => {
try {
let res = onRejected(this.reason)
resolvePromise(promise2, res, resolve, reject)
} catch (error) {
reject(error);
}
}, 0);
}
// 异步代码执行executor时:收集所有的成功或失败的回调函数
if (this.status == PENDING) {
// 订阅:收集成功函数
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let res = onFulfilled(this.value)
resolvePromise(promise2, res, resolve, reject)
} catch (error) {
reject(error);
}
}, 0);
})
// 订阅:收集失败函数
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let res = onRejected(this.reason)
resolvePromise(promise2, res, resolve, reject)
} catch (error) {
reject(error);
}
}, 0);
})
}
})
return promise2;
}
catch(errorCallback) {
return this.then(null, errorCallback)
}
resolve(value) {
return new MyPromise((resolve, reject) => {
resolve(value);
})
}
reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
})
}
//所有实例执行成功才算成功
all(promiseArray) {
if (!Array.isArray(promiseArray)) {
throw new TypeError(" The arguments should be an array!")
}
return new MyPromise((resolve, reject) => {
try {
const resultArray = [];
const length = promiseArray.length;
// 有一个实例失败直会接执行reject方法;
//否则等待所有实例执行完执行resolve方法
for (let i = 0; i < length; i++) {
promiseArray[i].then(data => {
resultArray.push(data);
if (resultArray.length === length) {
resolve(resultArray)
}
}, reject)
}
}
catch (e) {
reject(e)
}
})
}
// 返回第一个改变状态的结果,无论成功的还是失败的
race(promiseArray) {
if (!Array.isArray(promiseArray)) {
throw new TypeError(" The arguments should be an array!")
}
return new MyPromise((resolve, reject) => {
try {
const length = promiseArray.length;
for (let i = 0; i < length; i++) {
promiseArray[i].then(resolve, reject);
}
}
catch (e) {
reject(e)
}
})
}
}
// 处理then中成功函数或失败函数的返回值
function resolvePromise(promise2, res, resolve, reject) {
// 如果promise2等于res,抛出异常
// 例如:let promise1 = promise.then((value) => { return promise1; })
if (promise2 == res) {
return reject(new TypeError('Changing cycle detected for promise #<MyPromise>'))
}
// 如果res是一个object或function时
if ((typeof res === "object" && res !== null) || (typeof res === "function")) {
//保证res.then取值的时候出现异常
try {
let then = res.then;//判断是否为 promise 对象
//判断回调函数是否被多次调用过:例如 - resolve();resolve();连续多次调用
let called = false;
//为promise对象
if (typeof then === "function") {
then.call(res, (y) => {
// 避免重复调用
if (called) return;
called = true;
// 如果Y为Promise对象,递归调用
// 如果Y为普通值,相当于下次直接调用 - resolve()
resolvePromise(promise2, y, resolve, reject)
}, (r) => {
// 避免重复调用
if (called) return;
called = true;
reject(r)
})
}
else {
resolve(res);
}
} catch (error) {
// 避免重复调用
if (called) return;
called = true;
reject(error)
}
}
//res为普通值
else {
resolve(res);
}
}
module.exports = MyPromise;
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END