<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答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
        主站蜘蛛池模板: 亚洲一级毛片免费看| 亚洲伊人久久大香线蕉AV| 国产综合激情在线亚洲第一页| 美女被免费喷白浆视频 | 日日操夜夜操免费视频| 自拍偷区亚洲国内自拍| 免费亚洲视频在线观看| 免费人成在线观看播放国产| 国产A在亚洲线播放| 成人免费777777被爆出| 国产亚洲一区二区手机在线观看| 久久成人18免费网站| 国产精一品亚洲二区在线播放 | 成人免费777777被爆出| 国产精品亚洲片在线观看不卡| a级毛片毛片免费观看永久| 亚洲VA中文字幕不卡无码| 亚洲暴爽av人人爽日日碰| 成人免费视频国产| 免费一级特黄特色大片| 亚洲婷婷五月综合狠狠爱| 国产麻豆一精品一AV一免费| 在线观看亚洲人成网站| 88xx成人永久免费观看| 亚洲色成人网站WWW永久四虎 | 久久亚洲欧洲国产综合| 日本一区午夜艳熟免费| 波多野结衣免费视频观看| 无遮挡国产高潮视频免费观看| 亚洲中文字幕无码永久在线| 日韩人妻一区二区三区免费| 亚洲国产av美女网站| 国产男女猛烈无遮挡免费网站| 国产精品永久免费| 一级毛片直播亚洲| 好久久免费视频高清| 亚洲国产精品一区二区久| 又黄又爽的视频免费看| 国产精品视频白浆免费视频| 亚洲人成影院77777| 亚洲国产中文v高清在线观看|