promise 的 then
方法接受两个函数参数:
promise.then(onFulfilled, onRejected)
then((res) => {
console.log(res,“res”)
}, (error) => {
console.log(error,‘reason’)
})
2.1 onFulfilled
和 onRejected
都是可选参数。
-
如果
onFulfilled
不是函数,必须被忽略 -
如果
onRejected
不是函数,必须被忽略
2.2 onFulfilled
如果 onFulfilled
是函数:
-
当
promise
执行结束后其必须被调用,其第一个参数为promise
的value -
在
promise
执行结束前其不可被调用 -
其调用次数不可超过一次
new Promise((resolve, reject) => {
resolve(123)
}).then(result => {
console.log(result);
}, error => {
console.log(error);
});
// 这里resolve执行结束才会执行then,这里的result就是终值
2.3 onRejected
如果 onRejected
是函数:
-
当
promise
被拒绝执行后其必须被调用,其第一个参数为promise
的reason -
在
promise
被拒绝执行前其不可被调用 -
其调用次数不可超过一次
2.4 调用时机
onFulfilled
和 onRejected
只有在执行环境堆栈仅包含平台代码时才可被调用 >> 注1
2.5 调用要求
onFulfilled
和 onRejected
必须被作为函数调用(即没有 this
值)>> 注2
2.6 多次调用
then方法可以被同一个
promise 调用多次
-
当
promise
成功执行时,所有onFulfilled
需按照其注册顺序依次回调 -
当
promise
被拒绝执行时,所有的onRejected
需按照其注册顺序依次回调
new Promise.then().then()
2.7 返回
then
方法必须返回一个 promise
对象 >> 注3, 这也就是then可以被多次调用的原因。
Promise.prototype.then=function(onFulfilled, onRejected){
return new Promise()
}
promise2 = promise1.then(onFulfilled, onRejected);
- 如果
onFulfilled
或者onRejected
返回一个值x
,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
promise1.then((value)=>{
return x;
}, (reason)=>{
return x
}),
// 这种情况需要处理x函数还是值还是其他情况 ,所有用到了 Promise 解决过程
// 这种情况直接
Promise.prototype.then=function(onFulfilled, onRejected){
return let promise2 = new Promise((resolve,reject)=>{
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
}
- 如果
onFulfilled
或者onRejected
抛出一个异常e
,则promise2
必须拒绝执行,并返回拒因e
promise1.then((value)=>{
throw new Error()
}, (reason)=>{
throw new Error()
}),
// 这种情况直接
Promise.prototype.then=function(onFulfilled, onRejected){
return new Promise((resolve,reject)=>{
try {
// console.log(“执行 onFulfilled”);
// 这里的x是啥? 是then中回调的return的返回值
onFulfilled(this.value);
或者
onReject(this.reason)
} catch (e) {
reject(e);
}
})
}
- 如果
onFulfilled
不是函数且promise1
成功执行,promise2
必须成功执行并返回相同的值
promise1.then(1,2),
Promise.prototype.then=function(onFulfilled, onRejected){
if (this.status === STATUS_FULFILLED) {
return new Promise((resolve,reject)=>{
if(typeof onFulfilled !== “function” ){
resolve(onFulfilled)
}
if(typeof onRejected !== “function” ){
resolve(onRejected)
}
})
}
}
- 如果
onRejected
不是函数且promise1
拒绝执行,promise2
必须拒绝执行并返回相同的reason
promise1.then(1,2),
Promise.prototype.then=function(onFulfilled, onRejected){
if (this.status === STATUS_PENDING) {
return new Promise((resolve,reject)=>{
reject(onRejected)
})
}
}
Promise 解决过程是需要输入一个 promise 和一个值 x 的一个抽象的操作,称为 [[Resolve]](promise, x)
,如果 x
有 then
方法且看上去像一个 Promise ,解决程序即尝试使 promise
接受 x
的状态;否则其用 x
的值来执行 promise
。(x是返回值,请注意上面的例子)
解决过程步骤:
x
与 promise
相等
如果 promise
和 x
指向同一对象,直接 throw new TypeError
let p1=new Promise(resolve=>{
resolve()
})
let p2=p1.then(data=>{
// 返回了p2
return p2
})
x
是Promise
如果 x
是一个 Promise ,则使 promise
接受 x
的状态 >>注4:
-
如果
x
处于等待,promise
需保持等待直至x
被执行或拒绝 -
如果
x
处于执行,用相同的值执行promise
-
如果
x
处于拒绝,用相同的reason拒绝promise
x
为对象或函数
如果 x
为对象或者函数:
-
把
x.then
赋值给then
>> 注5 -
如果取
x.then
的值时抛出错误e
,则以e
为reason拒绝promise
-
如果then是函数,将x作为函数的作用域this调用。传递两个回调函数作为参数,第一个参数叫做resolvePromise
,第二个参数叫做rejectPromise:
-
如果
resolvePromise
以值y
为参数被调用,则运行[[Resolve]](promise, y)
-
如果
rejectPromise
以reasonr
为参数被调用,则以reasonr
拒绝promise
-
如果
resolvePromise
和rejectPromise
均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 -
如果调用then方法抛出了异常e:
-
如果
resolvePromise
或rejectPromise
已经被调用,则忽略之 -
否则以
e
为reason拒绝promise
-
如果
then
不是函数,以x
为参数执行promise
-
如果
x
不为对象或者函数,以x
为参数执行promise
function resolvePromise(promise2, x, resolve, reject) {
// 用来保存是否已经reject或者resolve过
let called
if (promise2 === x) {
throw new TypeError(‘Chaining cycle detected for promise’)
}
// 如果是函数或者object的话先默认是promise
if (x != null && (typeof x === ‘object’ || typeof x === ‘function’)) {
try {
let then = x.then
// 如果then是函数的话
if (typeof then === ‘function’) {
// 为啥不直接x.then()
// 因为then已经判断过是不是function,但是x.then没有判断过
// 就让then执行 第一个参数是this 后面是成功的回调 和 失败的回调
// 这里的y是啥,如果x是promsie的话,那么y就是x中的resolve/reject的值
算法刷题
大厂面试还是很注重算法题的,尤其是字节跳动,算法是问的比较多的,关于算法,推荐《LeetCode》和《算法的乐趣》,这两本我也有电子版,字节跳动、阿里、美团等大厂面试题(含答案+解析)、学习笔记、Xmind思维导图均可以分享给大家学习。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
写在最后
最后,对所以做Java的朋友提几点建议,也是我的个人心得:
-
疯狂编程
-
学习效果可视化
-
写博客
-
阅读优秀代码
-
心态调整