成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

nodejs源碼中的require問題

LiveVideoStack / 951人閱讀

摘要:提起中的模塊,就會想到用去加在引用那個模塊??戳瞬簧俨┛?,加載機制明白了,腦子里總是稀里糊涂的知道會每個文件會被文件的源碼包裹,自然也就有文件中的命令了。于是想寫寫記錄自己的整個過程。這就是幾個的關(guān)系。

提起nodejs中的模塊,就會想到用require去加在引用那個模塊。看了不少博客,加載機制明白了,腦子里總是稀里糊涂的知道會每個文件會被"(function (exports, require, module, __filename, __dirname) {",
// 文件的源碼
"n});"包裹,自然也就有文件中的require命令了。前幾天看了模塊的源碼 https://github.com/nodejs/nod...
module.js源碼的前幾行

const NativeModule = require("native_module");
const util = require("util");
const internalModule = require("internal/module");
const vm = require("vm");
const assert = require("assert").ok;
const fs = require("fs");
const internalFS = require("internal/fs");

一上來就懵了,module.js不就是為了實現(xiàn)require的嗎?為什么一上來就用require去引用其他模塊,從而陷入死循環(huán)。在一些技術(shù)網(wǎng)站提問https://cnodejs.org/topic/58b... 雖然還不是很明白,但得到了一些思路,然后又開始重新看源碼,并動手調(diào)試,總算想清楚了。于是想寫寫記錄自己的整個過程。

一、module.js前幾行的require從哪里來的

寫了兩個js文件,a.js

const b = require("./b.js");

b.js

exports.done = false;

node 執(zhí)行a.js
首先node啟動時會先執(zhí)行第一個js文件https://github.com/nodejs/nod...
這個文件中會定義module.js中第一行的NativeModule??梢钥吹絅ativeModule的定義

function NativeModule(id) {
this.filename = `${id}.js`;
this.id = id;
this.exports = {};
this.loaded = false;
this.loading = false;

}

從入口函數(shù)startup中可以看到

const Module = NativeModule.require("module");也就是說會去加載module.js模塊。

在require函數(shù)中

NativeModule.require = function(id) {
if (id === "native_module") {
  return NativeModule;
}
/..../
const nativeModule = new NativeModule(id);新建NativeModule對象

nativeModule.cache();
nativeModule.compile();  //主要步驟

return nativeModule.exports;

};

在compile中

NativeModule.prototype.compile = function() {
var source = NativeModule.getSource(this.id);
source = NativeModule.wrap(source);   

this.loading = true;

try {
  const fn = runInThisContext(source, {
    filename: this.filename,
    lineOffset: 0,
    displayErrors: true
  });
  fn(this.exports, NativeModule.require, this, this.filename);

  this.loaded = true;
} finally {
  this.loading = false;
}

};

wrap會進行文件的包裹

NativeModule.wrap = function(script) {
return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};

NativeModule.wrapper = [
"(function (exports, require, module, __filename, __dirname) { ",
"
});"
];

這里的require是NativeModule.require

接下來就會執(zhí)行Module.runMain函數(shù),從而進入module.js中,所以module
.js中開始的require是NativeModule.require,并不矛盾。

二、a.js的執(zhí)行情況
執(zhí)行a.js時則會通過bootstrap_node.js的runMain函數(shù)進入module.js

Module.runMain = function() {
// Load the main module--the command line argument.
Module._load(process.argv[1], null, true);
// Handle any nextTicks added in the first tick of the program
process._tickCallback();
};調(diào)用Module._load函數(shù),process.argv[1]為a.js


Module.runMain->Module._load->tryModuleLoad->module.load->Module._extensions[".js"]->module._compile

在module._compile中

var wrapper = Module.wrap(content);這個時候才調(diào)用NativeModule的wrap函數(shù)對a.js就行包裹

接下來

 var require = internalModule.makeRequireFunction.call(this);會通過
 https://github.com/nodejs/node/blob/master/lib/internal/module.js中的makeRequireFunction函數(shù)創(chuàng)造一個require函數(shù),
  function require(path) {
  try {
  exports.requireDepth += 1;
  return self.require(path);
} finally {
  exports.requireDepth -= 1;
}

}
call.(this)將指針指向module,從而a.js包裹的頭部中require就是makeRequireFunction返回的require,
self.require(path);則會調(diào)用用Module.prototype.require

Module.prototype.require = function(path) {
return Module._load(path, this, /* isMain */ false);
};
require則會調(diào)用 Module._load去加載其他模塊。

這就是幾個require的關(guān)系。

新人第一次寫,如有錯誤,還請糾正。

參考:
https://github.com/nodejs/nod...
https://github.com/nodejs/nod...
https://github.com/nodejs/nod...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81946.html

相關(guān)文章

  • 關(guān)于Node.js的__dirname,__filename,process.cwd(),./文件路

    摘要:先把當成文件,依次查找當前目錄下的,找到了,就返回該文件,不再繼續(xù)執(zhí)行。那么關(guān)于正確的結(jié)論是在中使用是跟的效果相同,不會因為啟動腳本的目錄不一樣而改變,在其他情況下跟效果相同,是相對于啟動腳本所在目錄的路徑。 起因 原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關(guān)注最新動態(tài),大家一起多交流學(xué)習(xí),共同進步,以學(xué)習(xí)者的身份寫博...

    harryhappy 評論0 收藏0
  • 關(guān)于Node.js的__dirname,__filename,process.cwd(),./文件路

    摘要:先把當成文件,依次查找當前目錄下的,找到了,就返回該文件,不再繼續(xù)執(zhí)行。那么關(guān)于正確的結(jié)論是在中使用是跟的效果相同,不會因為啟動腳本的目錄不一樣而改變,在其他情況下跟效果相同,是相對于啟動腳本所在目錄的路徑。 起因 原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關(guān)注最新動態(tài),大家一起多交流學(xué)習(xí),共同進步,以學(xué)習(xí)者的身份寫博...

    pumpkin9 評論0 收藏0
  • nodejs分析excel文件將結(jié)果寫入excel文件

    摘要:之后需要對中的結(jié)果數(shù)據(jù)做分析,并且制作圖表寫周報發(fā)給老大。輪到我值班的時候就用寫了一個腳本自動處理中的數(shù)據(jù),并且將數(shù)據(jù)再寫入文件。腳本目的讀取文件,分析中的數(shù)據(jù),并且將結(jié)果寫入中。 背景 因為 Team 本身工作性質(zhì)的問題,平時需要值班。值班數(shù)據(jù)可以導(dǎo)出為本地的Excel文件。之后需要對Excel中的結(jié)果數(shù)據(jù)做分析,并且制作圖表寫周報發(fā)給老大。 對于我這種對word都玩不轉(zhuǎn)的人,別說用...

    Alan 評論0 收藏0
  • 什么!?nodejs 實現(xiàn)的同步網(wǎng)絡(luò)請求?

    摘要:以異步方式事件隊列為標準,基本每一套與網(wǎng)絡(luò)相關(guān)的都會設(shè)計成異步的。在這種情況下,同步的網(wǎng)絡(luò)請求比異步的請求會更加合適,代碼更加清晰,邏輯更簡單,而且對代碼效率要求不高。如下,便是簡化后的同步請求,文本替換的代碼。 node.js 以異步方式、事件隊列為標準,基本每一套與網(wǎng)絡(luò)、IO 相關(guān)的 API 都會設(shè)計成異步的。 如,一段很平常的請求代碼,用 node.js 只能用異步方式。 con...

    Rindia 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<