/*
做之前先来看看我们promise的用法
*/
// let r = new Promise((resolve, reject) => {
// resolve("成功")
// })
// r.then((res) => {
// console.log(res)
// }, (err) => {
// console.log(err)
// })
/**
* 从上边的代码我们可以确定以下几件事
1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
2. Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
pending -> fulfilled
pending -> rejected
一旦状态确定就不可更改
3. resolve和reject函数是用来更改状态的
resolve: fulfilled
reject: rejected
4. then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的
5. then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
6. 同一个promise对象下面的then方法是可以被调用多次的
7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
*/
//接下来,我们先来简单实现上边功能,先把promise整体写个大概再来查缺补漏
// Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending,所以我们可以全局定义3个变量,方便调用
const PENDING = 'pending';
const RESOLVE = 'resolve';
const REJECT = 'reject';
class MyPromise {
// reject的实现是一样的,只是最后调用的是reject而不是resolve方法
static resolve(value) {
// 判断是否是thenable对象
if (value instanceof MyPromise || ((typeof value === 'object') && 'then' in value)) {
return value;
}
return new MyPromise((resolve) => resolve(value));//可以链式调用,所以要返回一个promise
}
static reject(value) {
// 判断是否是thenable对象
if (value instanceof MyPromise || ((typeof value === 'object') && 'then' in value)) {
return value;
}
return new MyPromise((reject) => reject(value));
}
static all(arr) {
let res = [] //结果
let num = 0 //看看是不是所有任务都执行完了
return new MyPromise((resolve, reject) => {
function addData(index, data) {
res[index] = data
num++;;
if (num === arr.length) {
//执行完就给结果
resolve(res)
}
}
for (let i = 0; i < arr.length; i++) {
let current = arr[i]//当前任务
if (current instanceof MyPromise) {
current.then((value) => { addData(i, value) }, (e) => { reject(e) })
} else {
addData(i, current)
}
}
})
}
static race(arr) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
let current = arr[i]//当前任务
// 这里使用 Promise.resolve 包了一下,以防传递了 non-promise
Promise.resolve(current).then(res => {
resolve(res);
}, error => {
reject(error);
});
}
})
}
constructor(fn) {
/*
new Promise , 需要传递一个执行器进去 执行器会立即执行,fn就是这个执行器,
可以看到应用的时候fn是会有两个方法回传回去的,分别是resolve和reject函数,所以我们来实现这两个方法
*/
fn(this.resolve, this.reject)
}
// 成功之后的值
value = undefined;
// 失败后的原因
reason = undefined;
// promsie 状态
status = PENDING;
//成功的异步回调
successCallback = [];
//失败的异步回调
failCallback = [];
//为了保证调用的时候this指向永远都指向类本身,这里用箭头函数的形式来定义
// resolve和reject函数是用来更改状态的
//resolve在调用的时候会接收一个值,用于返回给then第一个回调的参数,所以我们得定义一个变量(value),用于接收这个参数
resolve = (value) => {
//首先状态不可逆,所以先判断promise状态
if (this.status !== PENDING) return;
//接收resolve的值,等待then的调用
this.value = value
//接下来就是改状态了,resolve是成功,
this.status = RESOLVE
//调用成功的异步回调
this.successCallback.map(item => item && item())
}
//reject在调用的时候会接收一个值,用于返回给then第二个回调的参数,所以我们得定义一个变量(reason),用于接收这个参数
reject = (reason) => {
//首先状态不可逆,所以先判断promise状态
if (this.status !== PENDING) return;
//接收reject的值,等待then的调用
this.reason = reason
//接下来就是改状态了,reject是成功,
this.status = REJECT
//调用失败的异步回调
this.failCallback.map(item => item && item())
}
finally(callback) {
//会返回一个promise对象
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value);
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
/*
接下来实现then,then接收两个参数,分别是成功的回调和失败的回调
*/
then(resolveCallBack, rejectCallBack) {
// 参数可选
resolveCallBack = resolveCallBack ? resolveCallBack : value => value;
// 参数可选
rejectCallBack = rejectCallBack ? rejectCallBack : value => { throw value };
//then方法要实现链式调用就得返回一个新的promise对象
let promise2 = new MyPromise((resolve, reject) => {
//判断promise状态,来决定调用哪个方法
if (this.status === RESOLVE) {
setTimeout(() => {
try {
let r = resolveCallBack(this.value)
// 在then中的会返回值会作为下一次then的参数,所以这里封装了一个方法来调用
//为了在这里拿到promise2的值,所以用了定时器做了异步处理
//这里传promise2的目的是为了处理then返回自身promise的情况,做了一个报错处理
/* resolvePromise函数的作用
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
*/
resolvePromise(promise2, r, RESOLVE, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECT) {
setTimeout(() => {
try {
let r = rejectCallBack(this.reason)
resolvePromise(promise2, r, REJECT, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else {
//处理异步代码
this.successCallback.push(() => {
setTimeout(() => {
try {
let r = resolveCallBack(this.value);
resolvePromise(promise2, r, RESOLVE, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let r = rejectCallBack(this.reason);
resolvePromise(promise2, r, REJECT, resolve, reject)
} catch (e) {
reject(e);
}
}, 0)
})
}
})
return promise2
}
}
function resolvePromise(promise2, r, status, resolve, reject) {
if (promise2 === r) {
return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
}
if (r instanceof MyPromise) {
r.then(resolve, reject)
} else {
if (status === RESOLVE) {
resolve(r)
} else {
reject(r)
}
}
}
//测试用例1(基本功能)
//以上我们就完成了promise的基本功能,接下来我们看看我们自己的promise和原生的promise的测试结果是否一致
// let myPromise1 = new MyPromise((resolve, reject) => {
// resolve("myPromise1成功")
// reject("myPromise1失败")
// })
// myPromise1.then((res) => {
// console.log(res)
// }, (err) => {
// console.log(err)
// })
//测试用例2(promise中加入异步逻辑)
//在用例1中我们实现了promise的基本逻辑,接下来我们就来看看promise中加入异步逻辑怎么实现
/*
如用例2我们在定时器里resolve,有了异步代码,但按照我们用例1的代码肯定是无法做到和原生一样的
我们在then方法中还没有判断状态为pending的时候,因此我们应该定义两个数组,一个用来接收成功的的异步逻辑回调
一个用来接收失败的异步逻辑回调,在resolve或reject的时候来执行这些回调
*/
// let myPromise2 = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve("myPromise2成功")
// }, 10)
// // reject("myPromise2失败")
// })
// myPromise2.then((res) => {
// console.log(res)
// }, (err) => {
// console.log(err)
// })
//测试用例3(then的链式调用)
//注要实现then的链式调用,then方法的可选参数,错误捕获
// let myPromise3 = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve("myPromise3成功")
// }, 10)
// reject("myPromise3失败")
// })
// myPromise3.then((res) => {
// console.log(res)
// return "first"
// }, (err) => {
// console.log(err)
// return "失败"
// }).then((res) => {
// console.log(res)
// return "two"
// }, (err) => {
// console.log(err)
// }).finally(()=>{
// console.log("finally")
// }).catch((err)=>{
// console.log(err,"catch")
// })
//测试用例4(静态方法的实现)
//promise.resolve()
MyPromise.resolve("myPromise4成功").then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
//promise.reject()
MyPromise.reject("myPromise4失败").then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
//promise.all()
function p1() {
return new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve('成功1')
}, 4000)
})
}
function p2() {
return new MyPromise(function (resolve, reject) {
//reject('失败')
setTimeout(function () {
resolve('成功2');
}, 3000)
})
}
MyPromise.all([1, 2, p1(), p2(), 6]).then((res) => {
console.log(res, 'promise.all res')
}, (err) => {
console.log(err, 'promise.all err')
})
MyPromise.race([p1(), p2()]).then((res) => {
console.log(res, 'promise.race res')
}, (err) => {
console.log(err, 'promise.all err')
})
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END