内容
- 1. 初始结构搭建
- 2.resolve与reject结构搭建
- 3. resolve与reject代码实现
- 4. throw抛出异常改变状态
- 5. Promise对象状态只能修改一次
- 6. then方法执行回调
- 7. 异步任务回调的执行
- 8. 指定多个回调的实现
- 9. 同步任务下then方法返回结果
- 10. 异步任务下then方法返回结果
- 11. catch() - 异常穿透和值传递
- 12. promise API - resolve()封装
- 13. promise API - reject()封装
- 14. promise API - all()封装
- 15. promise API - race()封装
- 16. then()回调的异步执行
1. 初始结构搭建
2.resolve与reject结构搭建
3. resolve与reject代码实现
注意一下resolve
和reject
函数里如果直接使用this
的话是指向window
的,不是指向实例的
4. throw抛出异常改变状态
抛出异常会把promise
对象状态变为失败,且失败值是抛出的错误
try-catch
能处理throw
抛出的异常,try-catch
应该放在执行器函数
执行的地方
5. Promise对象状态只能修改一次
promise
对象的状态只能修改一次,只能从pending=>resolve
或者pending=>reject
也就是说如下代码输出的应该是一个成功的promise
对象
但是用我们自定义的promise
,得到了错误的结果
很简单,在我们的resolve
和reject
函数中都加入判断即可
6. then方法执行回调
这里能用this
,因为调用then()
方法的就是promise实例
,所以this
指向的就是promise实例
我们知道then()
方法的两个参数的函数有两个形参都是函数,那这里肯定是需要两个实参的,onResolved
和onRejected
,在对应状态改变了的时候调用这两个函数,并把结果值传进去
7. 异步任务回调的执行
现在我们要将处理的同步任务换成异步任务
如下面代码:
控制台没有输出任何东西
为什么?
因为当调用then()
方法的时候,resolve()
还没有执行,就是说promise
对象的状态还没改变
那我们的then()
方法的这两个判断都进不去
显然我们这里还需要再多加一个判断,
if(this.PromiseState) === 'pending{}'
在这个判断里面写一些东西
我们还需要注意的是then()
方法的onResolved
和onRejected
函数参数的执行时机,它们是在状态改变
之后执行,我们的状态改变
是在resolve()
和reject()
函数里,所以我们也需要在这两个函数里调用一下onResolved
和onRejected
函数
现在是调不到的,它们是不同的函数。所以我们需要保存回调函数,并且保存在自己身上
新增一个属性callback
:
判断状态为pending
时保存then()
的这两个回调函数
当改变了状态,就调用这两个回调函数:
8. 指定多个回调的实现
我们前面说过如果为一个promise
对象指定多个回调,这多个回调函数
都是会执行的
那么如下代码应该会输出ok和value
但是我们的promise
只输出了value
,显然执行的是第二个then()
方法的回调
也就是我们代码的这个位置,第一次进来的时候状态为pending
保存了回调,第二次进来还是pending
把第一次的回调覆盖掉了,那么这样会一次次覆盖掉之前的回调,事实上我们应该保存每一个回调
我们把callback
属性改成数组,再把每一次回调push()
进去:
打印一下我们的promise
对象,callback
中确实存好了这两次回调
那在状态改变之后调用回调函数的时候,应该遍历callback
,执行里面的每一次回调
9. 同步任务下then方法返回结果
复习一下:
then()
方法的返回结果是由它指定的回调函数的执行结果决定的
- 这个回调函数如果返回一个
非promise值
,then()
返回的promise对象
状态变为成功,成功值
就是回调函数的返回值
- 这个回调函数如果返回一个
promise对象
,这个promise对象
就决定了then()
返回的promise对象
- 这个回调函数如果抛出异常,
then()
返回的promise对象
状态变为失败,失败值
就是回调函数的抛出错误
现在我们就要来实现让then()
方法正确返回结果:
因为then()
返回的promise
的状态和结果取决于它指定的回调函数
的执行结果
,我们肯定要在这个执行结果res
上进行一些判断
- 如果回调函数返回
非promise值
,then()
返回的promise
状态会变为成功,所以在这就要调用resolve()
,而且成功值
就是回调函数的返回值
,也就是它的执行结果res
,把res
传进resolve()
- 如果回调函数返回一个
promise对象
,意味着这个执行结果res
是一个promise对象
,它也可以调用then()
方法。res
如果成功,意味着then()
返回的promise
状态也是成功的,因为这个执行结果res
返回的promise
决定了then()
返回的promise
,而且状态成功它就一定会执行then()
的第一个回调,所以在第一个回调里,就要调用resolve()
把then()
返回的promise
状态改为成功
,而且then()
返回的promise
的成功结果就是执行结果res
返回的promise
的成功结果,所以调用resolve()
的时候把value
传进去
(这部分太难口头说清楚了,废话有点多见谅,我自己也有点懵逼🤦♀️)
测试一下:
如果回调函数如果抛出异常,then()
也可以成功返回一个失败的promise对象
状态为rejected
的时候也跟上面差不多一样的,补全就好了
10. 异步任务下then方法返回结果
下面我们将同步任务改成异步任务
我们的then()
返回的结果显然是不正确的
分析一下我们的代码:
当实例p
调用我们的then()
时,因为改成异步任务了,p
的状态一定是pending
。那么就会进入了我们的第三个判断,在这里面我们即没有调用resolve()
也没有调用reject()
,那我们的then()
返回的promise
状态肯定是pending
了
在这单纯调用onResolved()
和onRejected()
这两回调已经不行了,得做点改进
下面这样,这个onResolved()
函数在实例p
状态改为成功
时会执行,onRejected()
在实例p
状态改为失败
时会执行
因为我们上面定义的resolve()
函数里把onResolved()
都取出来调用了
现在要思考的是在onResolved()
和onRejected()
中我们要做些什么
其实跟上面一样,同样也是分别在这两个函数里保存回调,根据回调来判断then()
返回的promise
的状态
11. catch() - 异常穿透和值传递
运行以下代码:
肯定会报错啦,毕竟我们都没有添加catch()
方法,下面来实现它
直接调用已经写好的then()
就行了
还要实现一个异常穿透
功能:
需要在then()
中加下面代码:
判断有没有传递onRejected
参数,如果没有传,我们就帮它加一个定义,把错误抛出
then()
还有一个值传递
功能,就是两个参数都不传:
像以下代码:
我们的promise
会报错
其实是因为第一个参数onResolved()
我们既没有传递也没有定义,我们可以再为它定义一下onResolved()
函数:
12. promise API - resolve()封装
resolve()
方法返回一个promise
,状态由传入的值决定,如果传入非promise值
=> 状态成功,且成功值为传入值
如果传入promise对象
=> 状态和结果由传入的promise对象
决定
注意一下这个方法属于promise函数对象
,不是属于promise实例对象
13. promise API - reject()封装
reject()
方法和resolve()
方法不同在于:reject()
方法返回的promise
状态永远是失败的,失败值就是传入值
14. promise API - all()封装
all()
接收一个由promise对象
组成的数组
,返回一个promise对象
,状态由数组中的promise对象
共同决定,所有的promise
都成功,才算成功,否则失败
15. promise API - race()封装
race()
也是接收一个由promise对象
组成的数组
,返回一个promise对象
,状态由数组中第一个改变状态
的promise对象
决定
谁先改变状态,谁就先执行回调,改变race()
返回的promise
的状态
16. then()回调的异步执行
then()
指定的回调函数
是异步执行
的,可以用下面代码测试内置的promise
:
可以看到then()
指定的回调中的代码是最后执行的,这就是因为它是异步执行
的,要等到同步执行代码执行完才会执行
用一下我们封装的promise
:
实现then()
指定的回调异步执行
:
在resolve()
和reject()
中调用回调函数的地方也要套:
改变状态之后,不要立即调用回调
完整版:
function Promise(executor) {
// 添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callback = [];
// 保存实例对象的this值
const self = this;
// resolve函数
function resolve(data) {
// 判断状态
if (self.PromiseState !== 'pending') {
return
}
// 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';
// 设置对象结果值 (promiseResult)
self.PromiseResult = data;
setTimeout(() => {
// 调用成功的回调函数
self.callback.forEach(item => {
item.onResolved(data);
})
})
}
// reject函数
function reject(data) {
// 判断状态
if (self.PromiseState !== 'pending') {
return
}
// 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';
// 设置对象结果值 (promiseResult)
self.PromiseResult = data;
// 调用失败的回调函数
self.callback.forEach(item => {
item.onRejected(data);
})
}
try {
// 同步调用执行器函数
executor(resolve, reject);
} catch (e) {
// 修改 promise 对象的状态为失败,而且失败的结果值就是抛出的错误
reject(e);
}
}
// 添加then 方法
Promise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 判断回调函数参数
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value;
}
return new Promise((resolve, reject) => {
// 调用回调函数
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
// 获取回调函数的执行结果
let res = onResolved(this.PromiseResult);
// 如果执行结果是promise类型的对象
if (res instanceof Promise) {
res.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
// 返回结果的对象状态为成功,成功值就是回调函数返回的值
resolve(res);
}
})
}
// 调用回调函数
if (this.PromiseState === 'rejected') {
setTimeout(() => {
// 获取回调函数的执行结果
let res = onRejected(this.PromiseResult);
// 如果执行结果是promise类型的对象
if (res instanceof Promise) {
res.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
// 返回结果的对象状态为成功,成功值就是回调函数返回的值
resolve(res);
}
})
}
// 判断pending状态
if (this.PromiseState === 'pending') {
// 保存回调函数
this.callback.push({
// onResolved,
onResolved() {
try {
// 保存成功的回调函数
let res = onResolved(self.PromiseResult);
if (res instanceof Promise) {
res.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
},
// onRejected
onRejected() {
// 保存失败的回调函数
let res = onRejected(self.PromiseResult);
if (res instanceof Promise) {
res.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(res);
}
}
})
}
})
}
// 添加catch方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
}
// 添加resolve方法
Promise.resolve = function (param) {
// 返回promise对象
return new Promise((resolve, reject) => {
// 由传递参数判断状态和结果值
if (param instanceof Promise) {
param.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
// 状态设置为成功
resolve(param);
}
})
}
// 添加reject方法
Promise.reject = function (param) {
return new Promise((resolve, reject) => {
reject(param);
})
}
// 添加all方法
Promise.all = function (param) {
return new Promise((resolve, reject) => {
// 计数成功的promise个数
let count = 0;
// 新数组,保存结果
let success = [];
// 遍历传入的数组
param.forEach(item => {
item.then(value => {
// 进入这个回调,说明成功,成功个数+1
count++;
// 成功值存进数组
success.push(value);
// 全部成功
if (count === param.length) {
resolve(success);
}
}, reason => {
reject(reason);
})
})
})
}
// 添加race方法
Promise.race = function (param) {
return new Promise((resolve, reject) => {
param.forEach(item => {
item.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
})
})
}
完