Recently also did not output article for a long time, the reason is very simple, recently huge busy ,,,,

Honestly, I’ve been pretty lost lately. About technology, about life. I also talked with a lot of friends in Dachang and wanted some ideas for later development. There was also talk about the interview and some questions that would be given to candidates in the recruitment process. I haven’t had an interview in a while, so I chose a few. A series of interview questions will be published soon.

Today’s track is bytedance:

Implement a batch request function multiRequest(urls, maxNum) with the following requirements: • maxNum specifies the maximum number of concurrent requests • Each time a request returns, a space is left for new requests to be added • When all requests are completed, the results are typed in the order in urlsCopy the code

This topic I think many students should be more or less seen, below I will turn from the scene, the analysis of the problem to the final implementation, step by step to give a simple and profound analysis of this topic.

scenario

Imagine a scenario where there are 30 asynchronous requests that need to be sent, but for some reason we have to limit the number of concurrent requests to five at a time and get the response as quickly as possible.

What should be done?

First, let’s look at serialization and parallelism of Ajax.

Serial and parallel Ajax implementation based on promise.all

We usually encapsulate asynchronous requests based on promises, and here we mainly expand for asynchronous requests.

  • Serial: an asynchronous request is followed by the next request
  • Parallelism: Multiple asynchronous requests are made simultaneously

Concretely demonstrate serialization/parallelism by defining some Promise instances.

serial

var p = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() = > {
      console.log('1000')
      resolve()
    }, 1000)})}var p1 = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() = > {
      console.log('2000')
      resolve()
    }, 2000)})}var p2 = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() = > {
      console.log('3000')
      resolve()
    }, 3000)
  })
}


p().then(() = > {
  return p1()
}).then(() = > {
  return p2()
}).then(() = > {
  console.log('end')})Copy the code

As an example, serial executes the corresponding interface requests from top to bottom.

parallel

When we need to ensure that code executes after multiple asynchronous processes, we use:

Promise.all(promises: []).then(fun: function);
Copy the code

Promise. All guarantees that all Promise objects in promises array will reach the resolve state before performing the THEN callback.

var promises = function () {
  return [1000.2000.3000].map(current= > {
    return new Promise(function (resolve, reject) {
      setTimeout(() = > {
        console.log(current)
      }, current)
    })
  })
}

Promise.all(promises()).then(() = > {
  console.log('end')})Copy the code

Promise.all Concurrency limit

Consider a scenario: If every object in your Promises array is an HTTP request, and there are hundreds of thousands of such objects.

What happens then is that you send hundreds of thousands of HTTP requests all at once, which is likely to result in a huge stack of calls that run out of memory.

At this point, we need to consider concurrency restrictions on promise.all.

Promise.all concurrency limit means that the number of concurrent promises executed at any time is fixed, and the final execution result remains the same as the original promise. all.

Subject to achieve

Thought analysis

The overall approach is recursive: the number of requests initially sent is capped at the maximum allowed, and each of these requests should continue to be sent recursively as it completes, with the incoming index determining which URL is in the urls, ensuring that the final output is not out of order, but in sequence.

Code implementation

function multiRequest(urls = [], maxNum) {
  // Total number of requests
  const len = urls.length;
  // Create an array based on the number of requests to hold the results of the requests
  const result = new Array(len).fill(false);
  // The current number of completions
  let count = 0;

  return new Promise((resolve, reject) = > {
    // Request maxNum
    while (count < maxNum) {
      next();
    }
    function next() {
      let current = count++;
      // Handle boundary conditions
      if (current >= len) {
        // When the request completes, set the promise to success and return result as a promise! result.includes(false) && resolve(result);
        return;
      }
      const url = urls[current];
      console.log(` began${current}`.new Date().toLocaleString());
      fetch(url)
        .then((res) = > {
          // Save the request result
          result[current] = res;
          console.log(Completed `${current}`.new Date().toLocaleString());
          // If the request is not complete, it is recursive
          if (current < len) {
            next();
          }
        })
        .catch((err) = > {
          console.log(End of `${current}`.new Date().toLocaleString());
          result[current] = err;
          // If the request is not complete, it is recursive
          if(current < len) { next(); }}); }}); }Copy the code