DDR爱好者之家 Design By 杰米
1. 循环require
在JavaScript中,模块之间可能出现相互引用的情况,例如现在有三个模块,他们之间的相互引用关系如下,大致的引用关系可以表示为 A -> B -> C -> A,要完成模块A,它依赖于模块C,但是模块C反过来又依赖于模块A,此时就出现了循环require。
// a.js const B = require('./b.js'); console.log('B in A', B); const A = { name: 'A', childName: B.name, }; module.exports = A;
// b.js const C = require('./c.js'); console.log('C in B', C); const B = { name: 'B', childName: C.name, } module.exports = B;
// c.js const A = require('./a.js'); console.log('A in C', A); const C = { name: 'C', childName: A.name, }; module.exports = C;
那JS引擎会一直循环require下去吗?答案是不会的,如果我们以a.js为入口执行程序,C在引用A时,a.js已经执行,不会再重新执行a.js,因此c.js获得的A对象是一个空对象(因为a.js还没执行完成)。
2. 小程序中的坑
在正常情况下,JS引擎是可以解析循环require的情形的。但是在一些低版本的小程序中,居然出现程序一直循环require的情况,最终导致栈溢出而报错,实在是天坑。
那如何解决呢,很遗憾,目前并未找到完美的方法来解决,只能找到程序中的循环require的代码,并进行修改。为了快速定位程序中的循环引用,写了一段NodeJs检测代码来检测进行检测。
const fs = require('fs'); const path = require('path'); const fileCache = {}; const requireLink = []; if (process.argv.length !== 3) { console.log(`please run as: node ${__filename.split(path.sep).pop()} file/to/track`); return; } const filePath = process.argv[2]; const absFilePath = getFullFilePath(filePath); if (absFilePath) { resolveRequires(absFilePath, 0); } else { console.error('file not exist:', filePath); } /** * 递归函数,解析文件的依赖 * @param {String} file 引用文件的路径 * @param {Number} level 文件所在的引用层级 */ function resolveRequires(file, level) { requireLink[level] = file; for (let i = 0; i < level; i ++) { if (requireLink[i] === file) { console.log('**** require circle detected ****'); console.log(requireLink.slice(0, level + 1)); console.log(); return; } } const requireFiles = getRequireFiles(file); requireFiles.forEach(file => resolveRequires(file, level + 1)); } /** * 获取文件依赖的文件 * @param {String} filePath 引用文件的路径 */ function getRequireFiles(filePath) { if (!fileCache[filePath]) { try { const fileBuffer = fs.readFileSync(filePath); fileCache[filePath] = fileBuffer.toString(); } catch(err) { console.log('read file failed', filePath); return []; } } const fileContent = fileCache[filePath]; // 引入模块的几种形式 const requirePattern = /require\s*\(['"](.*"]\)/g; const importPattern1 = /import\s+.*"](.*"]/g; const importPattern2 = /import\s+['"](.*"]/g; const requireFilePaths = []; const baseDir = path.dirname(filePath); let match = null; while ((match = requirePattern.exec(fileContent)) !== null) { requireFilePaths.push(match[1]); } while ((match = importPattern1.exec(fileContent)) !== null) { requireFilePaths.push(match[1]); } while ((match = importPattern2.exec(fileContent)) !== null) { requireFilePaths.push(match[1]); } return requireFilePaths.map(fp => getFullFilePath(fp, baseDir)).filter(fp => !!fp); } /** * 获取文件的完整绝对路径 * @param {String} filePath 文件路径 * @param {String} baseDir 文件路径的相对路径 */ function getFullFilePath(filePath, baseDir) { if (baseDir) { filePath = path.resolve(baseDir, filePath); } else { filePath = path.resolve(filePath); } if (fs.existsSync(filePath)) { const stat = fs.statSync(filePath); if (stat.isDirectory() && fs.existsSync(path.join(filePath, 'index.js'))) { return path.join(filePath, 'index.js'); } else if (stat.isFile()){ return filePath; } } else if (fs.existsSync(filePath + '.js')) { return filePath + '.js'; } return ''; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米
暂无评论...
更新日志
2024年11月25日
2024年11月25日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]