原来使用Promise
用法不再多说,只是展示比较跟我下面写的使用方法
var p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(4)
}, 0)
})
p.then((res)=>{
//4 res
console.log(res, 'res')
})
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve(4);
// eslint-disable-next-line prefer-promise-reject-errors
reject(4);
}, 0);
});
p.then(
(res) => {
console.log(res, 'res');
},
(err) => {
// 4 err
console.log(err, 'err');
},
);
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve(4);
// eslint-disable-next-line prefer-promise-reject-errors
reject(4);
}, 0);
});
p.then((res) => {
console.log(res, 'res');
}).catch((e) => {
// 4
console.log(e);
});
我们这里可以看到如果写入then
第二个参数后,可以处理reject
的值,也可以通过catch
来处理reject
的值
手写Promise
- 创建一个class 对象 新增构建函数
class MyPromise {
public constructor(fn: (resolve: (value: unknown) => void) => void) {
// 成功
const resolve = (value: unknown) => {
console.log(value);
};
fn(resolve);
}
}
const a = new MyPromise((resolve) => {
resolve('123');
/** 123 */
});
这样我们创建一个类,具有回调对象里面函数的方法。
- 新增状态,执行返回值,拒绝返回值
const PENDING = 'pending'; // 等待中
const FULFILLED = 'fulfilled'; // 执行
const REJECTED = 'rejected'; // 拒绝
class MyPromise {
/** 执行状态 */
state = PENDING;
/** 执行返回 */
value: any = null;
/** 失败返回 */
reason: any = null;
public constructor(
fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
) {
const resolve = (value: unknown) => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
console.log(value);
}
};
const reject = (reason: unknown) => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected';
// 储存失败的原因
this.reason = reason;
}
};
// 如果executor执行报错,直接执行reject
try {
fn(resolve, reject);
} catch (err) {
reject(err);
}
}
}
const a = new MyPromise((resolve) => {
resolve('123');
/** 123 */
});
现在跟Promise 使用方法还差一个then方法进行回调resolve
方法
3.
- 秘籍规定:Promise有一个叫做
then
的方法,里面有两个参数:onFulfilled
,onRejected
,成功有成功的值,失败有失败的原因 - 当状态
state
为fulfilled
,则执行onFulfilled
,传入this.value
。当状态state
为rejected
,则执行onRejected
,传入this.value
onFulfilled
,onRejected
如果他们是函数,则必须分别在fulfilled
,rejected
后被调用,value
或reason
依次作为他们的第一个参数。- 例子:以下是
Promise
,可以看得到resolve
传进去就是4
,这个值会传进then
里面的res
就是上面提到onFulfilled
var p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(4)
}, 0)
})
p.then((res)=>{
//4 res
console.log(res, 'res')
})
- 回到为我们这边
const PENDING = 'pending'; // 等待中
const FULFILLED = 'fulfilled'; // 执行
const REJECTED = 'rejected'; // 拒绝
class MyPromise {
/** 执行状态 */
state = PENDING;
/** 执行返回 */
value: any = null;
/** 失败返回 */
reason: any = null;
public constructor(
fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
) {
const resolve = (value: unknown) => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
}
};
const reject = (reason: unknown) => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected';
// 储存失败的原因
this.reason = reason;
}
};
// 如果executor执行报错,直接执行reject
try {
fn(resolve, reject);
} catch (err) {
reject(err);
}
}
// then 方法 有两个参数onFulfilled onRejected
then(onFulfilled?: Function, onRejected?: Function) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (onFulfilled && this.state === 'fulfilled') {
onFulfilled(this.value);
}
// 状态为rejected,执行onRejected,传入失败的原因
if (onRejected && this.state === 'rejected') {
onRejected(this.reason);
}
}
}
const a = new MyPromise((resolve) => {
resolve('123');
});
a.then((res: string) => {
console.log(res);
// 123
});
- 处理异步问题,现在基本可以实现简单的同步代码,但是当
resolve
在setTomeou
t内执行,then
时state
还是pending
等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject
或者resolve
,就调用它们,优化一下代码
enum Status {
PENDING = 'pending', // 等待中
FULFILLED = 'fulfilled', // 执行
REJECTED = 'rejected', // 拒绝
}
class MyPromise {
/** 执行状态 */
state: Status = Status.PENDING;
/** 执行返回 */
value: any = null;
/** 失败返回 */
reason: any = null;
/** 成功存放的数组 */
onResolvedCallbacks: Function[] = [];
/** 失败存放法数组 */
onRejectedCallbacks: Function[] = [];
public constructor(
fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
) {
const resolve = (value: unknown) => {
// state改变,resolve调用就会失败
if (this.state === Status.PENDING) {
// resolve调用后,state转化为成功态
this.state = Status.FULFILLED;
// 储存成功的值
this.value = value;
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
const reject = (reason: unknown) => {
// state改变,reject调用就会失败
if (this.state === Status.PENDING) {
// reject调用后,state转化为失败态
this.state = Status.REJECTED;
// 储存失败的原因
this.reason = reason;
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
// 如果executor执行报错,直接执行reject
try {
fn(resolve, reject);
} catch (err) {
reject(err);
}
}
// then 方法 有两个参数onFulfilled onRejected
then(onFulfilled?: Function, onRejected?: Function) {
if (this.state === Status.FULFILLED && onFulfilled) {
onFulfilled(this.value);
}
if (this.state === Status.REJECTED && onRejected) {
onRejected(this.reason);
}
// 当状态state为pending时
if (this.state === Status.PENDING) {
if (onFulfilled && typeof onFulfilled === 'function') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
});
}
if (onRejected && typeof onRejected === 'function') {
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
onRejected(this.value);
});
}
}
}
}
const a = new MyPromise((resolve) => {
setTimeout(() => {
console.log('444');
resolve('123');
}, 500);
console.log('333');
});
a.then((res: string) => {
console.log(res);
});
// 333 444 123 最终结果
- 如果上面的逻辑已经看懂后,接下来要看最关键的链式结构,意思是多个
then
使用, new Promise().then().then() ,这就是链式调用,用来解决回调地狱。
- 例子
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(4);
// eslint-disable-next-line prefer-promise-reject-errors
// reject(4);
}, 0);
});
p.then((res) => {
// 4 res
console.log(res, 'res');
return res + 1;
}).then((res) => {
// 5 res2
console.log(res, 'res2');
});
-
1、为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
•将这个promise2返回的值传递到下一个then中
•如果返回一个普通的值,则将普通的值传递给下一个then中 -
2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
-
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
-
回归我们代码
enum Status {
PENDING = 'pending', // 等待中
FULFILLED = 'fulfilled', // 执行
REJECTED = 'rejected', // 拒绝
}
class MyPromise {
/** 执行状态 */
state: Status = Status.PENDING;
/** 执行返回 */
value: any = null;
/** 失败返回 */
reason: any = null;
/** 成功存放的数组 */
onResolvedCallbacks: Function[] = [];
/** 失败存放法数组 */
onRejectedCallbacks: Function[] = [];
/** 构造方法 是一个方法,里面有2个传参,第一个是 resolve 是方法传参是 成功回调传参, 第二个是reject方法 里面的参数是失败回调 */
public constructor(
fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
) {
const resolve = (value: unknown) => {
// state改变,resolve调用就会失败
if (this.state === Status.PENDING) {
// resolve调用后,state转化为成功态
this.state = Status.FULFILLED;
// 储存成功的值
this.value = value;
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
const reject = (reason: unknown) => {
// state改变,reject调用就会失败
if (this.state === Status.PENDING) {
// reject调用后,state转化为失败态
this.state = Status.REJECTED;
// 储存失败的原因
this.reason = reason;
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
// 如果executor执行报错,直接执行reject
try {
fn(resolve, reject);
} catch (err) {
reject(err);
}
}
// then 方法 有两个参数onFulfilled 是指 then(res)的res res 就是 resolve()传进去的值 onRejected
then(onFulfilled?: Function, onRejected?: Function) {
// 声明返回的promise2
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === Status.FULFILLED && onFulfilled) {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
}
if (this.state === Status.REJECTED && onRejected) {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
}
// 当状态state为pending时
if (this.state === Status.PENDING) {
if (onFulfilled && typeof onFulfilled === 'function') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
});
}
if (onRejected && typeof onRejected === 'function') {
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
const x = onRejected(this.value);
this.resolvePromise(promise2, x, resolve, reject);
});
}
}
});
return promise2;
}
resolvePromise(
promise2: MyPromise,
x: any,
resolve: (value: unknown) => void,
reject: (value: unknown) => void,
) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<promise>'));
}
// 判断如果x是否是一个对象,判断函数是否是对象的方法有:typeof instanceof constructor toString
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
const then = x.then; // 取then可以报错,报错就走reject()
if (typeof then === 'function') {
// 用then.call()为了避免在使用一次x.then报错
then.call(
x,
(y: any) => {
console.log('y', y);
resolve(y); // 采用promise的成功结果,并且向下传递
},
(r: any) => {
reject(r); // 采用promise的失败结果,并且向下传递
},
);
} else {
resolve(x); // x不是一个函数,是一个对象
}
} catch (err) {
reject(err);
}
} else {
// x是一个普通值
resolve(x);
}
}
}
使用demo
new MyPromise((resolve) => {
setTimeout(() => {
console.log('开始');
resolve('a');
}, 500);
})
.then((res: string) => {
console.log(res);
console.log('结束');
return 'b';
})
.then((res: string) => {
console.log(res);
});
new Promise((resolve) => {
resolve('a');
})
.then((res: any) => {
console.log(res);
return 'b';
})
.then((res: string) => {
console.log(res);
});
结果都是一样的可以使用