Please improve the sum function so that the sum(1,2,3,4,5,6) function returns 21. AsyncAdd function needs to be called in the sum function for numerical calculation, and asyncAdd function cannot be modified

The title

/** * Call this function in the sum function to complete the numerical calculation *@param {*} The first value of a to add, star@param {*} The second value of b that I'm going to add, star@param {*} The callback function */ after the callback is added
function asyncAdd(a,b,callback) {
  setTimeout(function(){
   callback(null, a+b)
  },1000)}/** * Call asyncAdd in this method to complete the numerical calculation *@param  {... any} Rest passes in the argument */
async function sum(. rest) {
  // Please complete the code here
}

let start = window.performance.now()
sum(1.2.3.4.5.6).then(res= > {
  Make sure that after calling sum, the result 21 is returned
  console.log(res)
  console.log('Total time of program execution:The ${window.performance.now() - start}`)})Copy the code

The problem can be divided into three levels of difficulty according to the output time of the program

  • Bronze difficulty, output time is greater than 6 seconds
  • Silver difficulty, the output time is greater than 3 seconds
  • On King difficulty, the output time is greater than 1 second

The answer

  • Bronze is difficult
async function sum(. rest) {
  // Take out the first value as the initial value
  let result = rest.shift()
  // Iterate over rest with "for of"
  for(let num of rest) {
    // Use promise to get the sum result
    result = await new Promise(resolve= > {
      asyncAdd(result, num, (_,res) = > {
        resolve(res)
      })
    })
  }
  // Returns the execution result
  return result
}

// The execution succeeds, and the execution duration is longer than 6 seconds
sum1(1.2.3.4.5.6).then(res= > {
  console.log('The calculation result is:${res}`)})Copy the code
  • Silver is difficult

In bronze, we add each item in the array. However, some optimizations can also be made to execute multiple executions concurrently, such as sum(1,2,3,4,5,6), which can be executed simultaneously with 1+2,3+4,5+6 to improve execution efficiency

async function sum(. rest) {
  // If less than two values are passed, return directly
  if (rest.length <= 1) {
    return rest[0] | |0
  }
  const promises = []
  // Execute the array in pairs
  for (let i = 0; i < rest.length; i += 2) {
    promises.push(
      new Promise(resolve= > {
        // If rest[I +1] is undefined, the array length is odd, this is the last one
        if (rest[i + 1= = =undefined) {
          resolve(rest[i])
        } else {
          // Call asyncAdd to calculate
          asyncAdd(rest[i], rest[i + 1].(_, result) = > {
            resolve(result)
          })
        }
      })
    )
  }
  // get the result of the first calculation
  const result = await Promise.all(promises)
  // then we call sum again for the first result [3,7,11]
  return awaitsum(... result) }// The execution is successful, and the execution duration is longer than 3 seconds but less than 4 seconds
sum1(1.2.3.4.5.6).then(res= > {
  console.log('The calculation result is:${res}`)})Copy the code
  • The king is difficult
async function sum(. rest) {
  let result = 0
  // Implicit conversion, object + number, calls the toString method of the object first
  const obj = {}
  obj.toString = function() {
    return result
  }
  const promises = []
  for(let num of rest) {
    promises.push(new Promise((resolve) = > {
      asyncAdd(obj, num, (_, res) = > {
        resolve(res)
      })
    }).then(res= > {
      // After the result value is changed, the return value of obj.toString is changed, and the next setTimeout call uses the new value
      result = res
    }))
  }
  await Promise.all(promises)
  return result
}

// The execution succeeds. The execution duration is longer than 1 second but less than 2 seconds
sum1(1.2.3.4.5.6).then(res= > {
  console.log('The calculation result is:${res}`)})Copy the code

Because JS is executed in a single thread, in the above code, we put all the calculations into promises array in for of, and then execute them in one go through promise.all without considering which two numbers to add first. Because of the single-threaded nature, we can guarantee that each Promise is executed in sequence, and the return value of obj. ToString is the return value of the previous Promise.