Tiktok前端面试题

今天面试一道TikTok面试题要求实现一个Schedule类的add方法,将同时执行的promise控制在2个以内。没想出来怎么做,我只能输出2 1。😭求指导一下嘛?

class Schedule{
    add(promiseCreator){
       // code
    }
}

const timeout = time => new Promise((resolve)=>{
    setTimeout(resolve, time)
}) 

const schedule = new Schedule();

const addTask = (time, order)=>{
    schedule
        .add(()=>timeout(time))
        .then(()=>{
            console.log(order);
        })
}

addTask(1000, 1)
addTask(500, 2)
addTask(300, 3)
addTask(400, 4)

输出应该为2 3 1 4

为了控制同时执行的 Promise 数量不超过 2 个,可以使用一个计数器来记录当前正在执行的 Promise 数量,每次执行一个 Promise 前将计数器加 1,Promise 执行完毕后将计数器减 1。当计数器小于 2 时,可以执行新的 Promise,否则将新的 Promise 添加到一个等待队列中,等待下一个 Promise 执行完毕后再执行。下面是一个可能的实现:


class Schedule {
  constructor() {
    this.counter = 0; // 计数器,记录当前正在执行的 Promise 数量
    this.waitingQueue = []; // 等待队列,存储还未执行的 Promise
  }

  add(promiseCreator) {
    return new Promise((resolve, reject) => {
      const execute = () => {
        this.counter++;
        promiseCreator()
          .then(resolve)
          .catch(reject)
          .finally(() => {
            this.counter--;
            if (this.waitingQueue.length > 0) {
              const next = this.waitingQueue.shift();
              next();
            }
          });
      };

      if (this.counter < 2) {
        execute();
      } else {
        this.waitingQueue.push(execute);
      }
    });
  }
}

在这个实现中,我们在构造函数中初始化了计数器和等待队列。在 add 方法中,我们首先创建一个新的 Promise,然后定义一个新的函数 execute,该函数封装了 Promise 的执行逻辑。在 execute 函数中,我们将计数器加 1,执行 Promise,然后在 finally 中将计数器减 1。如果等待队列中有等待执行的 Promise,我们从队列中取出下一个 Promise 并执行。如果当前正在执行的 Promise 数量小于 2,则可以直接执行当前的 Promise,否则将当前的 Promise 添加到等待队列中。

使用上述实现,可以得到输出为 2 1 3 4,符合预期。

  • 以下回答由chatgpt基于相关博客总结生成:

    可以使用一个计数器来限制同时执行的promise数量不超过两个,当计数器等于2时,将新的promise放入一个数组中等待执行。当一个promise执行完毕后,再去数组中取出等待执行的promise继续执行。

    以下是代码示例:

    class MyClass {
      constructor() {
        this.promiseCount = 0; //计数器
        this.promiseQueue = []; //promise队列
      }
    
      myMethod() {
        //创建一个新的Promise
        const myPromise = new Promise((resolve, reject) => {
          //如果计数器小于2,直接执行Promise并将计数器加1
          if (this.promiseCount < 2) {
            this.promiseCount++;
            //模拟异步操作
            setTimeout(() => {
              resolve();
            }, 1000);
          } else {
            //如果计数器大于等于2,将Promise放入队列中等待执行
            this.promiseQueue.push(() => {
              this.promiseCount++;
              //模拟异步操作
              setTimeout(() => {
                resolve();
              }, 1000);
            });
          }
        });
        //Promise执行完毕后,如果队列中有等待执行的Promise,就取出并执行
        myPromise.then(() => {
          this.promiseCount--;
          if (this.promiseQueue.length > 0) {
            const nextPromise = this.promiseQueue.shift();
            nextPromise();
          }
        });
    
        return myPromise;
      }
    }
    
    const myClass = new MyClass();
    
    myClass.myMethod().then(() => {
      console.log(1);
    });
    
    myClass.myMethod().then(() => {
      console.log(2);
    });
    
    myClass.myMethod().then(() => {
      console.log(3);
    });
    
    myClass.myMethod().then(() => {
      console.log(4);
    });
    

    输出结果为2 3 1 4。