npm获取函数名称和测试js脚本

这边遇到一个类似于测试的需求,需要从一个js文件里获取函数名,然后尝试执行这些函数和创建实例。这边首先遇到了一个问题是如何动态获取js里的函数名和类名,我这边暂时没找到特别好的方法,已有的方法都是类似于提取语法树那种提取函数名

最后想的还是通过正则匹配函数名来尝试执行,有参数需求的函数尝试用数字代替作为参数尽量执行,加了个5秒超时

附:安装npm
https://nodejs.org/en

安装minimist(用于调用参数)

bash 复制代码
npm i minimist

调用

bash 复制代码
node tester.js --fp sample.js

代码:

javascript 复制代码
const fs = require('fs');
const path = require('path');

console.log("--fp指定路径");
var args = require('minimist')(process.argv.slice(2));
console.log("filepath:",args.fp);
// 目标文件路径
const targetPath = path.join(__dirname, args.fp);

// 读取index.js文件内容
const fileContent = fs.readFileSync(targetPath, 'utf8');

// 正则表达式匹配函数名和类名
const functionRegex = /function\s+(\w+)\s*\(/g;
const classRegex = /class\s+(\w+)/g;
const arrowFunctionRegex =  /([a-zA-Z_\$][a-zA-Z_\$0-9]*)\s*=\s*\([^)]*\)\s*=>/g;
// const arrowFunctionRegex = /^([^\(\)]+)\s*=>/;

const functions = [];
const classes = [];

// 匹配函数名
let match;
while ((match = functionRegex.exec(fileContent)) !== null) {
  functions.push(match[1]);
}
while ((match = arrowFunctionRegex.exec(fileContent)) !== null) {
  functions.push(match[1]);
}

// 匹配类名
while ((match = classRegex.exec(fileContent)) !== null) {
  classes.push(match[1]);
}

if (!fileContent.includes('module.exports')) {
  fs.writeFileSync(
    targetPath,
    fileContent +
      `\nmodule.exports = {${functions.join(',') + ',' + classes.join(',')}}`
  );
}

const newRequire = require(targetPath);

/**
*@name asyncFunction
*@des 异步函数
*@param use: () => void | unknow
*@return {Promise}
 */

const  asyncFunction = async(use) => {
  return new Promise( (resolve, reject) => {
    // 异步操作,例如 Ajax 请求或者定时器
    try {
        const result = use();
        if(result) resolve(result)
    } catch (error) {
        reject(error)
    }
  });
}

// -- timeout 机制
function withTimeout(promise, timeout) {
  return Promise.race([
    promise,
    new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('操作超时'));
      }, timeout);
    })
  ]);
}

// 处理类的方法
const onHandleClassFn = async (ClassName, target, name) => {
  const params = [];
  for (let i = 0; i < target.length; i++) {
    params.push('拟参' + i);
  }
  if (!/^class\s/.test(Function.prototype.toString.call(target))) {
    try {
      const result = await withTimeout(
        asyncFunction(() => {
        return target.length
            ? 
            target(...params)
            : 
            target()
        }),
        5000
      );
        console.log(`---------类${ClassName}的${name}()的return结果:`, result);
    } catch (error) {
      console.log(`+++++++++抛出错误类${ClassName}的${name}()函数执行出错,error信息:`, error);
    } 
  }
};
for (const iterator in newRequire) {
  const target = newRequire[iterator];
  const params = [];
  for (let i = 0; i < target.length; i++) {
    params.push('拟参' + i);
  }
  if (!/^class\s/.test(Function.prototype.toString.call(target))) {
    try {
      target.length
        ? console.log(
            `---------以上是${iterator}()执行的log,return:`,
            target(...params),
            '---------'
          )
        : console.log(
            `---------以上是${iterator}()执行的log,return:`,
            target(),
            '---------'
          );
      continue;
    } catch (error) {
      console.log(`+++++++++抛出错误函数${iterator}执行出错,error:`, error);
    }
  }
  const Instance = target.length ? new target(...params) : new target();
  // 获取构造函数包含的所有方法
  const methods = Object.getOwnPropertyNames(Instance.__proto__).filter(
    (item) => item !== 'constructor'
  );

  methods.forEach((item) => {
    onHandleClassFn(iterator, Instance[item], item);
  });
}

用于测试的脚本

javascript 复制代码
function AFn() {
  console.log('Run Function A');
  return 'AFn is true'
}
function BFn(param1, param2) {
  console.log('Run Function B', param1, param2);
  return 'BFn is true'
}
const CFn = (param1, param2) => {
  console.log('Run Function C', param1, param2);
  return 'CFn is true'
}
class Cat {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  Say1(param1) {
    console.log('Say1方法参数:', param1);
    return 'Say1 is ' + +new Date();
  }
  Say2(param1,param2) {
    console.log('say2方法参数:', param1, param2);
    return 'Say2 is ' + +new Date();
  }
  ThrowerrFn(){
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('这是一个异步模拟抛error出错误的函数');
        reject('this is a error_throw');
      }, 200);
    })
  }
  ThrowSuccessFn(){
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log('这是一个异步模拟success的函数');
        resolve('success') 
      }, 2000);
    })
  }
  ThrowTimeoutFn(){
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve('timeout_success, 此结果会因为超时被阻塞输出')
      }, 6000);
    })
  }
  Say3(param1,param2) {
    console.log('say3方法参数:', param1, param2);
    return 'Say3 is ' + +new Date();
  }
}

module.exports = {AFn,BFn,CFn,Cat}
相关推荐
艾小码16 分钟前
手把手教你实现一个EventEmitter,彻底告别复杂事件管理!
前端·javascript·node.js
Jedi Hongbin3 小时前
Three.js shader内置矩阵注入
前端·javascript·three.js
加载中3613 小时前
pnpm时代包版本不一致问题还是否存在
前端·面试·npm
掘金安东尼3 小时前
Node.js 如何在 2025 年挤压 I/O 性能
前端·javascript·github
得物技术4 小时前
前端日志回捞系统的性能优化实践|得物技术
前端·javascript·性能优化
ZKshun4 小时前
[ 前端JavaScript的事件流机制 ] - 事件捕获、冒泡及委托原理
javascript
薛定谔的算法4 小时前
JavaScript栈的实现与应用:从基础到实战
前端·javascript·算法
魔云连洲5 小时前
React中的合成事件
前端·javascript·react.js
唐•苏凯6 小时前
ArcGIS Pro 遇到严重的应用程序错误而无法启动
开发语言·javascript·ecmascript
萌萌哒草头将军6 小时前
🚀🚀🚀 Oxc 恶意扩展警告;Rolldown 放弃 CJS 支持;Vite 发布两个漏洞补丁版本;Rslib v0.13 支持 ts-go
前端·javascript·vue.js