How to get the return value of the setTimeout inner function in js All In One

乎语百科 240 0

How to get the return value of the setTimeout inner function in js All In One

在 js 中如何获取 setTimeout 内部函数的返回值

Promise wrap & Async / Await

How to get the return value of the setTimeout inner function in js All In One

raise a question

提出问题

如何获取 setTimeout 的返回值,以便可以自动化测试,即可以使用测试用例模版,跑通所有测试用例?

error

How to get the return value of the setTimeout inner function in js All In One

question analysis

问题分析

正常思路下,是不可能实现的,因为 setTimeout 是一个异步宏任务不会阻塞 js 单线程的执行,优先级最低,最后才会被执行; 故测试用例中执行读取结果的代码逻辑获取不到它的返回值,即测试代码逻辑已经执行了,结果还没返回;

那既然 setTimeout 是异步的,那就想办法阻塞它,让它的结果先返回,然后再执行读取结果的代码逻辑; 所以很容易想到使用 Promise 把 setTimeout 包装成一个微任务,然后通过 Async/Await 来进行异步流程的控制

Try it out

尝试验证

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2022-10-18
 * @modified
 *
 * @description js debounce
 * @description  js debounce
 * @difficulty Medium
 * @time_complexity O(n)
 * @space_complexity O(n)
 * @augments
 * @example
 * @link https://www.cnblogs.com/xgqfrms/p/13849482.html
 * @solutions
 *
 * @best_solutions
 *
 */

const log = console.log;

// function debounce(func) {
//   var id;
//   return function (args) {
//     console.log(`args 1 =`, args);
//     var context = this;
//     // var args = arguments;
//     clearTimeout(id);
//     id = setTimeout(() => {
//       // func.apply(context, args);
//       // func.apply(context, [...args]);
//       func.apply(context, ...args);
//       // Uncaught TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function
//     });
//   };
// };

// function debounce(func, delay) {
//   let id;
//   //  ...rest 保证在不使用 arguments 的情况下,也可以传入不定数量的参数
//   return function (...args) {
//     console.log(`\nrest args =`, args);
//     console.log(`rest ...args =`, ...args);
//     console.log(`rest [...args] =`, [...args]);
//     let args1 = arguments;
//     let args2 = Array.prototype.slice.call(arguments, 0);
//     console.log(`args1 =`, args1);
//     console.log(`args2 =`, args2);
//     let context = this;
//     // let that = this;
//     clearTimeout(id);
//     id = setTimeout(() => {
//       //  apply 接受参数数组 [arg1, arg2, ...]
//       func.apply(context, args);
//       // func.apply(context, [...args]);
//       // func.apply(context, ...args);
//       // Uncaught TypeError: CreateListFromArrayLike called on non-object
//       //  call 接受参数列表 (arg1, arg2, ...)
//       func.call(context, ...args2);
//     }, delay);
//   };
// };

const debounce = (func, delay) => {
  let id;
  //  ...rest 保证在不使用 arguments 的情况下,也可以传入不定数量的参数
  return async (...args) => {
    console.log(`\nrest args =`, args);
    console.log(`rest ...args =`, ...args);
    console.log(`rest [...args] =`, [...args]);
    let context = this;
    // let that = this;
    clearTimeout(id);
    // id = setTimeout(() => {
    //   //  apply 接受参数数组 [arg1, arg2, ...]
    //   func.apply(context, args);
    //   // func.apply(context, [...args]);
    //   //  call 接受参数列表 (arg1, arg2, ...)
    //   // func.call(context, ...args);
    // }, delay);
    const promise = new Promise((resolve, reject) => {
      id = setTimeout(() => {
        resolve(func.apply(context, args));
      }, delay);
    });
    // return promise;
    const result = await(promise);
    console.log(`result`, result);
    return result;
    // js how to get setTimeout inner function return value  promise wrap  & async / await
  };
};

// function test (a, b, c, d) {
//   const args = [...arguments];
//   console.log(`test args =`, args);
// }

// const fn = debounce(test, 1000);

// fn(1,2,3);
// // fn(1,2,3,4);
// fn(1,2,3,4,5);

// 测试用例 test cases
const testCases = [
  {
    input: [1,2,3],
    result: '1,2,3',
    desc: 'value equal to "1,2,3"',
  },
  {
    input: [1,2,3,4],
    result: '1,2,3,4',
    desc: 'value equal to "1,2,3,4"',
  },
  {
    input: [1,2,3,4,5],
    result: '1,2,3,4,5',
    desc: 'value equal to "1,2,3,4,5"',
  },
];

function test (a, b, c, d) {
  const args = [...arguments];
  console.log(`test args =`, args);
  return args;
}

const func = debounce(test, 1000);

log(`func =`, func);
// func = [AsyncFunction (anonymous)]
// func = Promise { [Function (anonymous)] }

(async () => {
  for (const [i, testCase] of testCases.entries()) {
    async function testCaseAsyncFunc(i, testCase) {
      const result = await func(...testCase.input);
      log(`result =`, result);
      // result = Promise { <pending> }
      // TypeError: func is not a function
      log(`test case ${i} result: `, result.join() === testCase.result ? ` passed` : ` failed`, result);
      // log(`test case ${i} =`, testCase);
    }
    await testCaseAsyncFunc(i, testCase);
  }
})();

solutions

得出结论

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2022-10-18
 * @modified
 *
 * @description How to get the return value of the setTimeout inner function in js All In One
 * @description 在 js 中如何获取 setTimeout 内部函数的返回值
 * @difficulty Hard
 * @time_complexity O(n)
 * @space_complexity O(n)
 * @augments
 * @example
 * @link https://www.cnblogs.com/xgqfrms/p/16806941.html
 * @link https://www.cnblogs.com/xgqfrms/p/13849482.html
 * @solutions
 *
 * @best_solutions
 *
 */

const log = console.log;

// 1. no need return value
/*

function debounce(func, delay) {
  let id;
  //  ...rest 保证在不使用 arguments 的情况下,也可以传入不定数量的参数
  return function (...args) {
    let that = this;
    clearTimeout(id);
    id = setTimeout(() => {
      //  apply 接受参数数组 [arg1, arg2, ...]
      func.apply(that, args);
      // func.apply(context, [...args]);
      //  call 接受参数列表 (arg1, arg2, ...)
      // func.call(context, ...args2);
    }, delay);
  };
};

function test (a, b, c, d) {
  const args = [...arguments];
  console.log(`test args =`, args);
}

const fn = debounce(test, 1000);

fn(1,2,3);
fn(1,2,3,4);
fn(1,2,3,4,5);

*/

// 2. setTimeout with return value
const debounce = (func, delay) => {
  let id;
  //  ...rest 保证在不使用 arguments 的情况下,也可以传入不定数量的参数
  return async (...args) => {
    console.log(`\nrest args =`, args);
    console.log(`rest ...args =`, ...args);
    console.log(`rest [...args] =`, [...args]);
    let that = this;
    clearTimeout(id);
    const result = await new Promise((resolve, reject) => {
      id = setTimeout(() => {
        //  apply 接受参数数组 [arg1, arg2, ...]
        resolve(func.apply(that, args));
      }, delay);
    });
    return result;
    // const promise = new Promise((resolve, reject) => {
    //   id = setTimeout(() => {
    //     //  apply 接受参数数组 [arg1, arg2, ...]
    //     resolve(func.apply(that, args));
    //   }, delay);
    // });
    // const result = await(promise);
    // console.log(`result =`, result);
    // return result;
  };
};

// 测试用例 test cases
const testCases = [
  {
    input: [1,2,3],
    result: '1,2,3',
    desc: 'value equal to "1,2,3"',
  },
  {
    input: [1,2,3,4],
    result: '1,2,3,4',
    desc: 'value equal to "1,2,3,4"',
  },
  {
    input: [1,2,3,4,5],
    result: '1,2,3,4,5',
    desc: 'value equal to "1,2,3,4,5"',
  },
];

function test (a, b, c, d) {
  const args = [...arguments];
  console.log(`test args =`, args);
  return args;
}

const func = debounce(test, 1000);

log(`func =`, func);
// func = [AsyncFunction (anonymous)]

(async () => {
  for (const [i, testCase] of testCases.entries()) {
    async function testCaseAsyncFunc(i, testCase) {
      const result = await func(...testCase.input);
      log(`result =`, result);
      log(`test case ${i} result: `, result.join() === testCase.result ? ` passed` : ` failed`, result);
      // log(`test case ${i} =`, testCase);
    }
    await testCaseAsyncFunc(i, testCase);
  }
})();

js debounce & js throttle

如何使用 js 实现一个 debounce 函数 All In One

https://www.cnblogs.com/xgqfrms/p/13849482.html

如何使用 js 实现一个 throttle 函数 All In One

https://www.cnblogs.com/xgqfrms/p/13849487.html

refs

https://splunktool.com/how-to-make-javascript-settimeout-returns-value-in-a-function

https://stackoverflow.com/questions/24928846/get-return-value-from-settimeout



xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有️xgqfrms, 禁止转载 ️,侵权必究️!


标签:

留言评论

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~