小编之前写过一篇:前端面试之问到promise怎么办?,温故而知新哦
怎么今天又来一篇与promise的文章呢 ,哈哈哈哈小伙伴们不要急着离开哈,是因为认识了一个去找实习的同学,聊了实习找的怎样了,让我印象最深刻的就是她讲promise的面试题,她说一面结束后就知道凉凉了,并且要是有机会很想和面试官说一句:面试官对不起!我终于会了Promise!
大概是这么个情况,所以呀小编又来讲讲promise,后面带有面试题。同学参加的是某大厂面试,大家看看面试题及同学的回答就知道这位同学有多难受了。
问了面试官对CSS的理解(必须但非重要,前端的核心还是尽量一比一还原设计稿,只有写好了页面才能考虑交互)
如何学习(基础是最重要的,CSS和JS要注重实践,盖房子最重要的还是地基,所有的框架源码,组件等都基于CSS和JS)
曾经是如何度过这个过程的(多做项目,在项目中学习理解每个细节,再次告诫我基础的重要性)
Promise是ES6新增的引用类型,可以通过new来进行实例化对象。Promise内部包含着异步的操作。
new Promise(fn)
Promise.resolve(fn)
这两种方式都会返回一个 Promise 对象。
知道了这些,我们可以得到下面的代码:
class Promise {
constructor() {
this.state = 'pending' // 初始化 未完成状态
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
}
}
复制代码
Promise状态只能在内部进行操作,内部操作在Promise执行器函数执行。Promise必须接受一个函数作为参数,我们称该函数为执行器函数,执行器函数又包含resolve和reject两个参数,它们是两个函数。
let p1 = new Promise((resolve,reject) => {
resolve(value);
})
setTimeout(() => {
console.log((p1)); // Promise {: undefined}
},1)
let p2 = new Promise((resolve,reject) => {
reject(reason);
})
setTimeout(() => {
console.log((p2)); // Promise {: undefined}
},1)
复制代码
所以得到如下代码:
class Promise{
constructor(executor){
// 初始化state为等待态
this.state = 'pending';
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
let resolve = value => {
console.log(value);
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
console.log('fulfilled 状态被执行');
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
}
};
let reject = reason => {
console.log(reason);
if (this.state === 'pending') {
// reject调用后,state转化为失败态
console.log('rejected 状态被执行');
this.state = 'rejected';
// 储存失败的原因
this.reason = reason;
}
};
// 如果 执行器函数 执行报错,直接执行reject
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
}
复制代码
检验一下上述代码咯:
class Promise{...} // 上述代码
new Promise((resolve, reject) => {
console.log(0);
setTimeout(() => {
resolve(10) // 1
// reject('JS我不爱你了') // 2
// 可能有错误
// throw new Error('是你的错') // 3
}, 1000)
})
复制代码
promise.then(onFulfilled, onRejected)
class Promise {
constructor(executor) {
this.state = 'pending' // 初始化 未完成状态
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// .then 立即执行后 state为pengding 把.then保存起来
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
// 把异步任务 把结果交给 resolve
let resolve = (value) => {
if (this.state === 'pending') {
console.log('fulfilled 状态被执行');
this.value = value
this.state = 'fulfilled'
// onFulfilled 要执行一次
this.onResolvedCallbacks.forEach(fn => fn());
}
}
let reject = (reason) => {
if (this.state === 'pending') {
console.log('rejected 状态被执行');
this.reason = reason
this.state = 'rejected'
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject)
}
catch (e) {
reject(err)
}
}
// 一个promise解决了后(完成状态转移,把控制权交出来)
then(onFulfilled, onRejected) {
if (this.state == 'pending') {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
console.log('then');
// 状态为fulfilled 执行成功 传入成功后的回调 把执行权转移
if (this.state == 'fulfiiied') {
onFulfilled(this.value);
}
// 状态为rejected 执行失败 传入失败后的回调 把执行权转移
if (this.state == 'rejected') {
onRejected(this.reason)
}
}
}
let p1 = new Promise((resolve, reject) => {
console.log(0);
setTimeout(() => {
// resolve(10)
reject('JS我不爱你了')
console.log('setTimeout');
}, 1000)
}).then(null,(data) => {
console.log(data, '++++++++++');
})
复制代码
0
then
rejected 状态被执行
JS我不爱你了 ++++++++++
setTimeout
复制代码
当resolve在setTomeout内执行,then时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们。
现可以异步实现了,但是还是不能链式调用啊? 为保证 then 函数链式调用,then 需要返回 promise 实例,再把这个promise返回的值传入下一个then中。
catch 异常处理函数,处理前面回调中可能抛出的异常。只接收一个参数onRejected处理程序。它相当于调用Promise.prototype.then(null,onRejected),所以它也会返回一个新的Promise
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10)
}, 1000)
}).then(() => {
throw Error("1123")
}).catch((err) => {
console.log(err);
})
.then(() => {
console.log('异常捕获后可以继续.then');
})
复制代码
当第一个.then的异常被捕获后可以继续执行。
Promise.all()创建的Promise会在这一组Promise全部解决后在解决。也就是说会等待所有的promise程序都返回结果之后执行后续的程序。返回一个新的Promise。
let p1 = new Promise((resolve, reject) => {
resolve('success1')
})
let p2 = new Promise((resolve, reject) => {
resolve('success1')
})
// let p3 = Promise.reject('failed3')
Promise.all([p1, p2]).then((result) => {
console.log(result) // ['success1', 'success2']
}).catch((error) => {
console.log(error)
})
// Promise.all([p1,p3,p2]).then((result) => {
// console.log(result)
// }).catch((error) => {
// console.log(error) // 'failed3'
//
// })
复制代码
有上述例子得到,all的性质:
Promise.race()是一组集合中最先解决或最先拒绝的Promise,返回一个新的Promise。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success1')
},1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('failed2')
}, 1500)
})
Promise.race([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 'success1'
})
复制代码
有上述例子得到,race的性质:
上面的Promise就总结到这里,有什么理解也可以在下方评论区一起交流学习。
面试可以让自己发现更多的知识盲点,从而促进自己学习,大家一起加油冲呀!!
这篇文章小伙伴们也别忘了点赞+评论噢!!!