国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

關于node.js和macOS之間的故事

來源:懂視網 責編:小采 時間:2020-11-27 20:10:11
文檔

關于node.js和macOS之間的故事

關于node.js和macOS之間的故事:本文由一個小故事來和大家分享關于node.js和macOS之間的故事,希望能幫助到大家。喬治G在他的電腦上做了一個小測試,但結果和預期的大不相同。那么我們先來看看這個小測試都寫了什么:一共三個文件,代碼總計不超過15行parent.jsclass Parent {}
推薦度:
導讀關于node.js和macOS之間的故事:本文由一個小故事來和大家分享關于node.js和macOS之間的故事,希望能幫助到大家。喬治G在他的電腦上做了一個小測試,但結果和預期的大不相同。那么我們先來看看這個小測試都寫了什么:一共三個文件,代碼總計不超過15行parent.jsclass Parent {}
本文由一個小故事來和大家分享關于node.js和macOS之間的故事,希望能幫助到大家。

喬治G在他的電腦上做了一個小測試,但結果和預期的大不相同。

那么我們先來看看這個小測試都寫了什么:

一共三個文件,代碼總計不超過15行

parent.js

class Parent {}

module.exports = Parent

son.js

//加載時把模塊文件名首字母大寫了(不正確的)
const Parent = require('./Parent')

class Son extends Parent {}

module.exports = Son

test.js

//加載時把模塊名首字母大寫(不正確的)
const ParentIncorrect = require('./Parent')
//通過正確的模塊文件名加載(正確)
const Parent = require('./parent')

const Son = require('./son')

const ss = new Son()

//測試結果
console.log(ss instanceof Parent) // false
console.log(ss instanceof ParentIncorrect) // true

喬治G同學有以下疑問:

  1. son.jstest.js 里都有錯誤的文件名(大小寫問題)引用,為什么不報錯?

  2. 測試結果,為什么 ss instanceof ParentIncorrect === true ?不報錯我忍了,為什么還認賊作父,說自己是那個通過不正確名字加載出來的模塊的instance?

如果同學你對上述問題已經了然于胸,恭喜你,文能提筆安天,武能上馬定乾坤;上炕認識娘們,下炕認識鞋!

但如果你也不是很清楚為什么?那么好了,我有的說,你有的看。

其實斷癥(裝逼范兒的debug)之法和中醫看病也有相似指出,望、聞、問、切四招可以按需選取一二來尋求答案。

代碼不多,看了一會,即便沒有我的注釋,相信仔細的同學也都發現真正的文件名和代碼中引入時有出入的,那么這里肯定是有問題的,問題記住,我們繼續

這個就算了,代碼我也聞不出個什么鬼來

來吧,軟件工程里很重要的一環,就是溝通,不見得是和遇到bug的同事,可能是自己,可能是QA,當然也可能是PM或者你的老板。你沒問出自己想知道的問題;他沒說清楚自己要回答的;都完蛋。。

那么我想知道什么呢?下面兩件事作為debug的入口比較合理:

  1. 操作系統

  2. 運行環境 + 版本

  3. 你怎么測試的,命令行還是其他什么手段

答曰:macOS; node.js > 8.0 ;命令行 node test.js

激動人心的深刻到來了,我要動手了。(為了完整的描述 debug 過程,我會假裝這下面的所有事情我事先都是不知道的)

準備電腦,完畢

準備運行環境 node.js > 9.3.0 , 完畢

復刻代碼,完畢

運行,日了狗,果然沒報錯,而且運行結果就是喬治G說的那樣。

為了證明我沒瞎,我又嘗試在 test.jsrequire 了一個壓根不存在的文件 require('./nidayede') ,運行代碼。

還好這次報錯了 Error: Cannot find module './nidayede' ,所以我沒瘋。這點真令人高興。

于是有了第一個問題

為什么狗日的模塊名大小寫都錯了,還能加載?

會不會和操作系統有關系?來我們再找臺 windows 試試,果然,到了 windows 上,大小寫問題就是個問題了, Error: Cannot find module './Parent'

那么 macOS 到底在干什么?連個大小寫都分不出來么?于是趕緊 google (別問我為什么不baidu)

原來人家牛逼的 OS X 默認用了 case-insensitive 的文件系統( 詳細文檔 )。

but why?這么反人類的設計到底是為了什么?

更多解釋, 來,走你

所以,這就是你不報錯的理由?(對 node.js 指責道),但這就是全部真相了。

但事情沒完

那認賊作父又是個什么鬼?

依稀有聽過 node.js 里有什么緩存,是那個東西引起的么?于是抱著試試看的心情,我把 const ParentIncorrect = require('./Parent')const Parent = require('./parent') 換了下位置,心想,這樣最先按照正確的名字加載,會不會就對了呢?

果然, 還是不對 。靠猜和裝逼是不能夠真正解決問題的

那比比 ParentIncorrectParent 呢?于是我寫了 console.log(ParentIncorrect === Parent) ,結果為 false 。所以他倆還真的不是同一個東西,那么說明問題可能在引入的部分嘍?

于是一個裝逼看 node.js 源碼的想法誕生了(其實不看,問題最終也能想明白)。 日了狗,懷著忐忑的心情,終于 clone 了一把 node.js 源碼(花了好久,真tm慢)

來,我們一起進入神秘的 node.js 源碼世界。既然我們的問題是有關 require 的,那就從她開始吧,不過找到 require 定義的過程需要點耐心,這里不詳述,只說查找的順序吧

src/node_main.cc => src/node.cc => lib/internal/bootstrap_node.js => lib/module.js

找到咯,就是這個 lib/module.js ,進入正題:

lib/module.js => require

Module.prototype.require = function(path) {
assert(path, 'missing path');
assert(typeof path === 'string', 'path must be a string');
return Module._load(path, this, /* isMain */ false);
};

好像沒什么卵用,對不對?她就調用了另一個方法 _load ,永不放棄,繼續

lib/module.js => _load

Module._load = function(request, parent, isMain) {
//debug代碼,么卵用,跳過
if (parent) {
debug('Module._load REQUEST %s parent: %s', request, parent.id);
}

if (isMain && experimentalModules) {
//...
//...
//這段是給ES module用的,不看了啊
}

//獲取模塊的完整路徑
var filename = Module._resolveFilename(request, parent, isMain);

//緩存在這里啊?好激動有沒有?!?終于見到她老人家了
//原來這是這樣的,簡單的一批,毫無神秘感啊有木有
var cachedModule = Module._cache[filename];
if (cachedModule) {
updateChildren(parent, cachedModule, true);
return cachedModule.exports;
}

//加載native但非內部module的,不看
if (NativeModule.nonInternalExists(filename)) {
debug('load native module %s', request);
return NativeModule.require(filename);
}

//構造全新Module實例了
var module = new Module(filename, parent);

if (isMain) {
process.mainModule = module;
module.id = '.';
}

//先把實例引用加緩存里
Module._cache[filename] = module;

//嘗試加載模塊了
tryModuleLoad(module, filename);

return module.exports;
};

似乎到這里差不多了,不過我們再深入看看 tryModuleLoad

lib/module.js => tryModuleLoad

function tryModuleLoad(module, filename) {
var threw = true;
try {
//加載模塊
module.load(filename);
threw = false;
} finally {
//要是加載失敗,從緩存里刪除
if (threw) {
delete Module._cache[filename];
}
}
}

接下來就是真正的 load 了,要不我們先停一停?

好了,分析問題的關鍵在于不忘初心,雖然到目前為止我們前進的比較順利,也很爽對不對?。但我們的此行的目的并不是爽,好像是有個什么疑惑哦!于是,我們再次梳理下問題:

  1. son.js 里用首字母大寫(不正確)的模塊名引用了 parent.js

  2. test.js 里,引用了兩次 parent.js ,一次用完全一致的模塊名;一次用首字母大寫的模塊名。結果發現 son instanceof require('./parent') === false

既然沒報錯的問題前面已經解決了,那么,現在看起來就是加載模塊這個部分可能出問題了,那么問題到底是什么?我們怎么驗證呢?

這個時候我看到了這么一句話 var cachedModule = Module._cache[filename]; ,文件名是作為緩存的 key ,來吧,是時候看看 Module._cache 里存的模塊 key 都是什么牛鬼蛇神了,打出來看看吧,于是我在 test.js 里最后面加了一句 console.log(Object.keys(require.cache)) ,我們看看打出了什么結果

false
true
[ '/Users/admin/codes/test/index.js',
'/Users/admin/codes/test/Parent.js',
'/Users/admin/codes/test/parent.js',
'/Users/admin/codes/test/son.js' ]

真相已經呼之欲出了, Module._cache 里真的出現了兩個 [p|P]arentmacOS 默認不區分大小寫,所以她找到的其實是同一個文件;但 node.js 當真了,一看文件名不一樣,就當成不同模塊了),所以最后問題的關鍵就在于 son.js 里到底引用時用了哪個名字(上面我們用了首字母大寫的 require('./Parent.js') ),這才導致了 test.js 認賊作父的梗。

如果我們改改 son.js ,把引用換成 require('./parEND.js') ,再次執行下 test.js 看看結果如何呢?

false
false
[ '/Users/haozuo/codes/test/index.js',
'/Users/haozuo/codes/test/Parent.js',
'/Users/haozuo/codes/test/parent.js',
'/Users/haozuo/codes/test/son.js',
'/Users/haozuo/codes/test/parENT.js' ]

沒有認賊作父了對不對?再看 Module._cache 里,原來是 parENT.js 也被當成一個單獨的模塊了。

所以,假設你的模塊文件名有 n 個字符,理論上,在 macOS 大小寫不敏感的文件系統里,你能讓 node.js 將其弄出最大 2n 次方個緩存來

是不是很慘!?還好 macOS 還是可以改成大小寫敏感的,格盤重裝系統;新建分區都行。

問題雖然不難,但探究問題的決心和思路還是重要的。

相關推薦:

教大家如何利用node.js創建子進程

PHP與Node.js

node.js 發布訂閱模式的方法

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

關于node.js和macOS之間的故事

關于node.js和macOS之間的故事:本文由一個小故事來和大家分享關于node.js和macOS之間的故事,希望能幫助到大家。喬治G在他的電腦上做了一個小測試,但結果和預期的大不相同。那么我們先來看看這個小測試都寫了什么:一共三個文件,代碼總計不超過15行parent.jsclass Parent {}
推薦度:
標簽: Mac js 例子
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 欧美日韩国产一区 | 另类欧美日韩 | 亚洲国产成人精品女人久久久 | 成人中文字幕一区二区三区 | 精品亚洲一区二区 | 国产成人综合精品一区 | 国产全黄a一级毛片 | 特黄一级毛片 | 黑人一区二区三区中文字幕 | 欧美极品在线观看 | 中文字幕一区二区三区四区 | 国产成人一区在线播放 | 99久久精品费精品国产一区二区 | 亚洲人一区| 午夜精品一区二区三区在线观看 | 伊人一级| 亚洲国产成人精品91久久久 | 欧美特黄一区二区三区 | 免费一级毛片视频 | 一区免费在线观看 | 久久频道毛片免费不卡片 | 亚洲青草视频 | 国内视频一区二区三区 | 欧美日韩国 | 国产成人精品第一区二区 | 性殴美 | 一级毛片视频免费 | 亚洲国产成人久久综合一区 | 日韩视频在线播放 | 日韩最新视频一区二区三 | 国产成人久久精品二区三区 | 日韩亚洲欧美视频 | 国产免费一区二区三区免费视频 | 欧美日韩国产在线播放 | 精品国产91乱码一区二区三区 | 手机国产精品一区二区 | 欧美日韩在线精品一区二区三区 | 国产欧美日韩精品第二区 | 欧美a一| 久久一区二区三区四区 | 国产成人三级经典中文 |