乐趣区

关于前端:面试-考验你对-Promise-的熟度之进阶应用题

作者:HannahLin
起源:medium

有幻想,有干货,微信搜寻【大迁世界】关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

这一篇应该早在两年前就要写了,因为是当初面试某间出名的 Udxxx 线上课程的面试题,当初只能用我单薄的记忆回顾一下。要说进阶题是因为当初我自认为对 Promise 算理解,但遇到这种应用题还是被 KO。

有碰过 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 → 总共几个 task
  • maxTask: number = 3 → 一次最多执行几个 task
  • pendingTask: [number] = [promise, promise...] → 期待被执行的 task
  • completed:number → Track 胜利了几个 Tasks

写一个 promise 的 task 还算简略,

/**
 * @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

总感觉会但又不晓得怎麽解,其实须要一个很重要的货色 count,来计算你当初到底在执行哪一个 task

count→计算当初正在执行的 Task,若 count < 3 就会执行 task(),所以一开始会先执行 3 个 Tasks。

当其中一个 task 做完,count 就会 -1,而后持续做下一个 task

run(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… 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

退出移动版