真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

詳解小程序循環(huán)require之坑

1. 循環(huán)require

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出同心免費(fèi)做網(wǎng)站回饋大家。

在JavaScript中,模塊之間可能出現(xiàn)相互引用的情況,例如現(xiàn)在有三個(gè)模塊,他們之間的相互引用關(guān)系如下,大致的引用關(guān)系可以表示為 A -> B -> C -> A,要完成模塊A,它依賴于模塊C,但是模塊C反過來又依賴于模塊A,此時(shí)就出現(xiàn)了循環(huán)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引擎會(huì)一直循環(huán)require下去嗎?答案是不會(huì)的,如果我們以a.js為入口執(zhí)行程序,C在引用A時(shí),a.js已經(jīng)執(zhí)行,不會(huì)再重新執(zhí)行a.js,因此c.js獲得的A對(duì)象是一個(gè)空對(duì)象(因?yàn)閍.js還沒執(zhí)行完成)。

2. 小程序中的坑

在正常情況下,JS引擎是可以解析循環(huán)require的情形的。但是在一些低版本的小程序中,居然出現(xiàn)程序一直循環(huán)require的情況,最終導(dǎo)致棧溢出而報(bào)錯(cuò),實(shí)在是天坑。

那如何解決呢,很遺憾,目前并未找到完美的方法來解決,只能找到程序中的循環(huán)require的代碼,并進(jìn)行修改。為了快速定位程序中的循環(huán)引用,寫了一段NodeJs檢測(cè)代碼來檢測(cè)進(jìn)行檢測(cè)。

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);
}

/**
 * 遞歸函數(shù),解析文件的依賴
 * @param {String} file 引用文件的路徑
 * @param {Number} level 文件所在的引用層級(jí)
 */
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+.*?\s+from\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);
}

/**
 * 獲取文件的完整絕對(duì)路徑
 * @param {String} filePath 文件路徑
 * @param {String} baseDir 文件路徑的相對(duì)路徑
 */
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 '';
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


分享名稱:詳解小程序循環(huán)require之坑
文章地址:http://weahome.cn/article/jegcsg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部