Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

字节面试题:编写并发请求控制函数scheduler #115

Open
Twlig opened this issue Jul 19, 2022 · 0 comments
Open

字节面试题:编写并发请求控制函数scheduler #115

Twlig opened this issue Jul 19, 2022 · 0 comments

Comments

@Twlig
Copy link
Owner

Twlig commented Jul 19, 2022

处理并发请求,以下是模拟异步请求,需要编写并发请求控制函数scheduler:

let request1 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1);
    }, 2000);
  });

let request2 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(2);
    }, 1200);
  });

let request3 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(3);
    }, 100);
  });

let request4 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(4);
    }, 100);
  });

函数的用法如下:

let addRequest = scheduler(2);

addRequest(request1).then((res) => {
  console.log(res);
});

addRequest(request2).then((res) => {
  console.log(res);
});

addRequest(request3).then((res) => {
  console.log(res);
});

addRequest(request4).then((res) => {
  console.log(res);
});
//输出 2,3,4,1

scheduler函数实现:

精髓在于:

  • scheduler返回一个new Promise,通过resolve,reject来释放异步请求的结果。

  • tasks队列记录异步任务,以及resolve,reject函数,便于在得到异步结果的时候直接resolve或者reject。

  • 使用tasks和pengdingCount以闭包的形式,在每次触发addRequest的时候把异步请求添加到任务队列。

  • run函数的编写,每次调用addRequest,加入任务队列后就执行run。

  • run函数内部,要经过任务队列长度,pendingCount的大小决定是否可以执行异步请求。

  • 每次执行任务是以shift的形式从任务队列中取出事件。

function scheduler(max = 10) {
  let tasks = [],
    pendingCount = 0;

  function run() {
    if (tasks.length > 0 && pendingCount < max) {
      pendingCount++;
      const { task, resolve, reject } = tasks.shift();
      task()
        .then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        )
        .finally(() => {
          pendingCount--;
          run();
        });
    }
  }
  return function (task) {
    return new Promise((resolve, reject) => {
      tasks.push({ task, resolve, reject });
      run();
    });
  };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant