逃离二向箔
习题链接
蓝桥杯web逃离二向箔
逃离二向箔
现在地球上有n个飞船请求飞向月亮
飞船的发射舱一共只有10个,所以最多同时只能有10支飞船同时起飞
满舱的时候,就要等待其中一只飞船起飞
只要发射舱有空舱,新的飞船就要进入当中继续发射,如此循环往复直到飞船飞完
关键点
- promise的基础使用,promise有三种状态Pending进行中,Fulfilled已完成,Rejected已拒绝
- 完成意味着调用.then方法
- 拒绝意味着调用.catch方法
- 无论完成还是拒绝,最后都执行.finally方法(此方法可以不使用,本次解题未使用)
- 准备一个名为sendlist数组(名称看自己取名,若要遵循规范就使用驼峰命名),用于统计正在使用的发射舱,方便后期判断发射舱是否已满
- async 及其 await 的使用 解决满舱等待
- 当sendlist数组的length到达了max(最大发射舱数量),就要进行等待飞船的发射
- 要进行等待就要对方法前面使用async
- 对异步方法使用await,这里的异步方法是Promise.race(senlist) 注:这个异步方法下面在第四点会讲到,此处无需过多思考
- Promise中的race方法的使用 解决等待任意一支飞船的起飞
- 假设此时发射舱已满,进入等待状态了
- 那我们如何知道正在起飞的飞船中有飞船起飞或失败了,这就需要Promise对象中的race方法了
- 使用语法是Promise.race(promise数组) race方法是当promise数组中的任意首个元素触发了完成或者失败均会将结果返回,这样就达到了我们等待任意一支飞船的起飞的这一条件
代码实现
- 初试发射飞船
// 这个题目使用的是es6的中class // 在这个类里的构造器中已经设置好了发射舱的数量max,请求发射的飞船队列是requestQueue // 执行的方法是run // 创建空的数组作为正在使用的发射舱 let sendlist = []; // 尝试发射第一支飞机,无论发射成功失败,这个发射舱都应该空出来给下一个飞机使用 sendlist.push( this.requestQueue.shift()() // 从请求飞机队列中的飞机添加到发射舱中,并执行起飞操作 .then((res) => { this.render(res); // 调用写好的方法渲染到页面中 sendlist.shift(); // 空出发射舱 }) .catch((err) => { this.render(err); // 调用写好的方法渲染到页面中 sendlist.shift(); // 空出发射舱 }) ); - 发射全部飞船
let sendlist = []; // 进行全部发射 while (this.requestQueue.length > 0) { // 每次都会拉取请求队列中的飞机,直到 没有飞机要进行发射了 sendlist.push( this.requestQueue.shift()() .then((res) => { this.render(res); sendlist.shift(); }) .catch((err) => { this.render(err); sendlist.shift(); }) ); } - 满舱等待
// 发射舱已满的情况下要进行等待 其中任意一支飞机的起飞 // 涉及等待了就得想到await,而往往await和async是同时出现的 // 如何知道 任意一支飞机成功起飞或起飞失败 关键在promise.race 衍生一下:all是与race相反的,全部完成才会触发all async run(){ // ··· if (sendlist.length == this.max) await Promise.race(sendlist); // ··· }
以下是完整的代码
- 完整code
async run() { // TODO:待补充代码 let sendlist = []; while (this.requestQueue.length > 0) { sendlist.push( this.requestQueue.shift()() .then((res) => { this.render(res); sendlist.shift(); }) .catch((err) => { this.render(err); sendlist.shift(); }) ); if (sendlist.length == this.max) await Promise.race(sendlist); } }