最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2019年03月08日 09:42:28   作者:沒有角的牛  
這篇文章主要介紹了詳解小程序循環(huán)require之坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 循環(huán)require

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

2. 小程序中的坑

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

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

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 文件所在的引用層級
 */
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);
}

/**
 * 獲取文件的完整絕對路徑
 * @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 '';
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JavaScript實現(xiàn)HSL拾色器

    JavaScript實現(xiàn)HSL拾色器

    這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)HSL拾色器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • javascript?ES6中set集合、map集合使用方法詳解與源碼實例

    javascript?ES6中set集合、map集合使用方法詳解與源碼實例

    這篇文章主要介紹了javascript?ES6中set、map使用方法詳解與源碼實例,需要的朋友可以參考下
    2022-12-12
  • 深入分析javascript中console命令

    深入分析javascript中console命令

    console對象是JavaScript的原生對象,它有點像Unix系統(tǒng)的標(biāo)準(zhǔn)輸出stdout和標(biāo)準(zhǔn)錯誤stderr,可以輸出各種信息用來調(diào)試程序,而且還提供了很多額外的方法,供開發(fā)者調(diào)用。它的常見用途有兩個。顯示網(wǎng)頁代碼運行時的錯誤信息。提供了一個命令行接口,用來與網(wǎng)頁代碼互動。
    2016-08-08
  • 前端實現(xiàn)Excel文件導(dǎo)出功能的完整代碼解析(vue實現(xiàn)excel文件導(dǎo)出)

    前端實現(xiàn)Excel文件導(dǎo)出功能的完整代碼解析(vue實現(xiàn)excel文件導(dǎo)出)

    在Vue中實現(xiàn)導(dǎo)出Excel文件有多種方式,可以通過前端實現(xiàn),也可以通過前后端配合實現(xiàn),下面這篇文章主要給大家介紹了關(guān)于前端實現(xiàn)Excel文件導(dǎo)出功能(vue實現(xiàn)excel文件導(dǎo)出)的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • js如何引入wasm文件

    js如何引入wasm文件

    這篇文章主要介紹了js如何引入wasm文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • javascript輸入CD-KEY自動分割的代碼

    javascript輸入CD-KEY自動分割的代碼

    開發(fā)過程中用寫的一個腳本,記錄下來以備后用與他用,其中attributes["max"].nodeValue是取HTML自定義的 max屬性(兼容Firefox和IE)
    2010-10-10
  • input輸入框的自動匹配(原生代碼)

    input輸入框的自動匹配(原生代碼)

    功能要求:使用原生代碼實現(xiàn),不可使用任何框架、只針對英文字符進(jìn)行匹配,并且匹配到的內(nèi)容在菜單中加粗、通過鍵盤上的上下箭頭可以對菜單進(jìn)行選擇等等,感興趣的你可以參考下
    2013-03-03
  • 純前端使用ffmpeg實現(xiàn)視頻壓縮的具體方法及踩坑

    純前端使用ffmpeg實現(xiàn)視頻壓縮的具體方法及踩坑

    這篇文章主要給大家介紹了關(guān)于純前端使用ffmpeg實現(xiàn)視頻壓縮的具體方法及踩坑,要在前端使用FFmpeg進(jìn)行視頻壓縮,你可以使用FFmpeg的JavaScript,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • JS正則表達(dá)式替換字符串replace()方法實例代碼

    JS正則表達(dá)式替換字符串replace()方法實例代碼

    正則表達(dá)式是用于匹配字符串中字符組合的模式,在js中正則表達(dá)式是對象,這篇文章主要給大家介紹了關(guān)于JS正則表達(dá)式替換字符串replace()方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • jsp網(wǎng)頁搜索結(jié)果中實現(xiàn)選中一行使其高亮

    jsp網(wǎng)頁搜索結(jié)果中實現(xiàn)選中一行使其高亮

    在做搜索結(jié)果時為了好看需要將選中的行變的高亮些,下面有個不錯的示例,需要的朋友可以參考下
    2014-02-02

最新評論

茂名市| 镇赉县| 土默特右旗| 宝丰县| 襄垣县| 通海县| 隆化县| 大同市| 格尔木市| 金塔县| 河池市| 旺苍县| 阳山县| 潞西市| 鹤峰县| 海林市| 库尔勒市| 南和县| 酒泉市| 綦江县| 循化| 绥江县| 维西| 江安县| 满城县| 福泉市| 共和县| 邓州市| 郴州市| 喀什市| 岳池县| 乳山市| 滨海县| 禹城市| 南京市| 西峡县| 海兴县| 敦煌市| 兴安盟| 黔西| 胶南市|