作者: HannahLin
来源:medium
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。【[面试] 考验你对 Promise 的熟度之进阶应用题】这一篇应该早在两年前就要写了,因为是当初面试某间知名的 Udxxx 线上课程的面试题,现在只能用我薄弱的记忆回忆一下。要说进阶题是因为当初我自认为对 Promise 算了解,但遇到这种应用题还是被 KO。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
文章图片
有碰过 Promise 的人可能会觉得也没什么难的,就是处理非同步
async
。var p = num => new Promise((resolve, reject) => {
if(num <= 2) {
setTimeout(resolve('Success!'), Math.random()*1000);
return;
}
reject('Failure!')
});
p(1)
.then(res => { console.log(res)})
.catch( error => { console.log(error)});
// "Success!"
但除了比较常见的 fetch API,其实还有很多进阶应用呢!接下来这题就要考考大家对 Promise 的熟度,因为当初的我是真的完全不知道怎麽解啊…
来看题目吧
总共 10 个 tasks 一次 call 最多 3 个,每个 task 需要完成的时间都不同。
文章图片
请使用以下提供的范本,写出能完成这 10 个任务的方法。
/**
* @return { promise }
* 写一个执行 task 的 function
*/
function task(){}
class handleTask{
constructor(maxCount){
this.maxCount = maxCount;
this.pendingTask = [];
this.completed = 0;
}
run(tasks){}
}
依据题目与提供的函数先推断可能需要哪些变量:
totalTask: number = 10
→ 总共几个 taskmaxTask: number = 3
→ 一次最多执行几个 taskpendingTask: [number] = [promise, promise...]
→ 等待被执行的 taskcompleted:number → Track
成功了几个 Tasks
/**
* @return { promise }
* 写一个执行 task 的 function
*/
function task(){
return new Promise((resolve, reject) => {
console.log('running')
setTimeout(resolve(), Math.random()*1000) // 每个 task 所需时间不同,所以这边用 random
}).then(() => {
console.log('done')
}).catch(() => {
console.log('error')
})
}
但要写
run()
这个 method 时我完全卡住:- 不知道怎麽一次执行三次,是 run 3 次 task 吗?
- 那执行完要怎麽在执行别的 task 直到执行完 ?
count
,来计算你现在到底在执行哪一个 task
count
→计算现在正在执行的 Task,若 count < 3
就会执行 task()
,所以一开始会先执行 3 个 Tasks。当其中一个 task 做完,
count
就会 -1
,然后继续做下一个 taskrun(tasks){
if(this.count < this.maxCount){
this.count ++;
tasks().then(() => {
this.count --;
})
}
}
pendingTask 另一个重点就是
pendingTask
拿来存待处理的任务,所以一开始会是 [4,5,6,7,8,9,10]
,当 [1,2,3]
其中一个 task 先处理完就会抓 task 4
继续处理,pendingTask
也会变 [5,6,7,8,9,10]
如下图:文章图片
run(tasks){
if(this.count < this.maxCount){
this.count ++;
tasks().then(() => {
this.count --;
this.pendingTask.shift()
})
} else{
this.pendingTask.push(tasks);
}
}
class handleTask{
constructor(maxCount){
this.maxCount = maxCount;
// 3
this.count = 0;
this.pendingTask = [];
this.completed = 0;
}run(tasks){
if(this.count < this.maxCount){
this.count ++;
tasks().then(() => {
this.count --;
this.completed ++;
this.pendingTask.shift(0);
console.log('completed: ', this.completed)
})
} else{
this.pendingTask.push(tasks);
}
}
}function task () {
//... 略
}let myTask = new handleTask(3);
for(let i=0;
i< 10;
i++){
myTask.run(task);
}
出现问题: 总共才完成 3 个任务
But, 发现
completed
最后才等于 3 而已,代表只成功完成 3 个 tasks!一定是哪裡出问题了啊。解決 这是因为
myTask.run(task)
;
会一瞬间跑十次 (不管 task 有没有做完), pendingTask
一开始会是 [4,5,6,7,8,9,10] ,然后因为if(this.count < this.maxCount){
this.count ++;
//前三个 task 会陆续做完
tasks().then(() => {
this.count --;
this.pendingTask.shift(0);
})
}
真正只有
[1, 2, 3]
会跑进 if
裡面 run task
,而 pendingTask
虽然会是 [7, 8, 9, 10]
,但其实 [4, 5, 6]
都没有被执行 run:文章图片
为了继续执行剩下任务,应该要把
this.pendingTask.shift(0)
;
,改成if(this.pendingTask.length > 0) this.run(this.pendingTask.shift())
这时候蛮考验 JS 基本功的,若
this.pendingTask
是 [4,5,6,7,8,9,10]
,那this.pendingTask.shift()
会回传,4 ;
this.pendingTask
则变 [5,6,7,8,9,10]
,也就是把任务 4 继续丢尽 run
裡跑这样才能把所有任务都完成。代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:
https://medium.com/starbugs/%...
交流
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
文章图片
推荐阅读
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- 接口|axios接口报错-参数类型错误解决
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- JavaScript|JavaScript — 初识数组、数组字面量和方法、forEach、数组的遍历
- JavaScript|JavaScript — call()和apply()、Date对象、Math、包装类、字符串的方法
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- vue|Vue面试常用详细总结
- javascript|vue使用js-xlsx导出excel,可修改格子样式,例如背景颜色、字体大小、列宽等
- css|我用css精灵图拼接了自己的英文名字,不会还有人不知道精灵图技术吧()
- css|css三角的做法及其案例