Maison >interface Web >js tutoriel >L'histoire entre node.js et macOS
Cet article utilise une courte histoire pour partager avec vous l'histoire entre node.js et macOS. J'espère qu'il pourra aider tout le monde.
George G a fait un petit test sur son ordinateur, mais les résultats ont été bien différents de ceux attendus.
Alors regardons d'abord ce qui est écrit dans ce petit test :
Il y a trois fichiers au total, et le code total ne dépasse pas 15 lignes
<span style="font-size: 14px;">class Parent {}<br><br>module.exports = Parent<br></span>
<span style="font-size: 14px;">//加载时把模块文件名首字母大写了(不正确的)<br/>const Parent = require('./Parent')<br/><br/>class Son extends Parent {}<br/><br/>module.exports = Son<br/></span>
<span style="font-size: 14px;">//加载时把模块名首字母大写(不正确的)<br/>const ParentIncorrect = require('./Parent')<br/>//通过正确的模块文件名加载(正确)<br/>const Parent = require('./parent')<br/><br/>const Son = require('./son')<br/><br/>const ss = new Son()<br/><br/>//测试结果<br/>console.log(ss instanceof Parent) // false<br/>console.log(ss instanceof ParentIncorrect) // true<br/></span>
L'étudiant George G a les questions suivantes :
<code><span style="font-size: 14px;">son.js</span>
son.js et <code><span style="font-size: 14px;">test.js</span>
test.js ont des références de nom de fichier incorrectes (problèmes de cas). Pourquoi aucune erreur n’est-elle signalée ?
Résultat du test, pourquoi <span style="font-size: 14px;">ss instanceof ParentIncorrect === true</span>
<span style="font-size: 14px;">ss instanceof ParentIncorrect === true</span>
Si vous, camarade de classe, avez déjà une compréhension claire des problèmes ci-dessus, félicitations, vous pouvez écrire un stylo pour calmer le ciel, et vos arts martiaux peuvent montez à cheval pour déterminer le monde ; vous pouvez connaître votre mère sur le kang Montons sur le kang et apprenons les chaussures !
Mais si vous ne savez pas pourquoi ? D'accord, certains d'entre moi le diront, et certains d'entre vous le regarderont.
En fait, la méthode de diagnostic (débogage dans un style prétentieux) est similaire à celle de la médecine traditionnelle chinoise. Vous pouvez choisir une ou deux des quatre méthodes de regarder, sentir,. demander et palper pour trouver la réponse.
Il n'y a pas beaucoup de code Après l'avoir lu pendant un moment, même sans mes commentaires, je pense que les étudiants attentifs trouveront. le vrai fichier. S'il y a une différence entre le nom et le code lors de son introduction, alors il doit y avoir un problème ici. Souvenez-vous du problème, continuons
.
Même si, je ne sens rien dans le codeAllez, un Une partie très importante de l'ingénierie logicielle est que la communication ne se fait pas nécessairement avec des collègues qui rencontrent des bugs. Cela peut être vous-même, cela peut être le contrôle qualité, et bien sûr, cela peut être le PM ou votre patron. Vous n'avez pas posé la question que vous vouliez savoir, il n'a pas précisé à quoi il voulait répondre, c'est fini. . . .
Alors qu'est-ce que je veux savoir ? Les deux choses suivantes sont plus raisonnables comme entrée dans le débogage :
Système d'exploitation
Exécuter l'Environnement + version
Comment l'avez-vous testé, en ligne de commande ou par un autre moyen
<span style="font-size: 14px;">node.js > 8.0</span>
Réponse : macOS ; node.js > 8.0
<span style="font-size: 14px;">node test.js</span>
Le moment excitant et profond est arrivé, et je vais passer à l'action. (Afin de décrire en détail le processus de <span style="font-size: 14px;">debug</span>
<span style="font-size: 14px;">débug</span>
Préparer l'ordinateur, terminé
<span style="font-size: 14px;">node.js > 9.3.0</span>
Préparer l'environnement d'exécutionnode.js > 9.3.0
, Terminé
Copiez le code, Terminé
Exécutez-le, c'est incroyable, aucune erreur n'a été signalée et le résultat en cours d'exécution est ce que George G a dit de cette façon. <code><span style="font-size: 14px;">test.js</span>Pour prouver que je ne suis pas aveugle, j'ai réessayé <code><span style="font-size: 14px;">require</span>
test.js dans <span style="font-size: 14px;">require('./nidayede')</span>
<span style="font-size: 14px;">require</span>
<span style="font-size: 14px;">require('./nidayede')</span>
<span style="font-size: 14px;">Error: Cannot find module './nidayede'</span>
, Exécutez le code.
Heureusement, une erreur a été signalée cette fois Erreur : Impossible de trouver le module './nidayede'
Est-ce lié au système d'exploitation ? Venez trouver un autre <code><span style="font-size: 14px;">windows</span>
windows pour essayer. Effectivement, nous sommes arrivés à <code><span style="font-size: 14px;">windows</span><code><span style="font-size: 14px;">windows</span>Error: Cannot find module './Parent'
, la majuscule est un problème, Erreur : impossible de trouver le module './Parent'
. <span style="font-size: 14px;">macOS</span>
Alors, que fait <code><span style="font-size: 14px;">google</span>
macOS ? Ne savez-vous pas faire la différence entre les majuscules et les minuscules ? Alors vite
<p>google<img src="https://img2./UZb2Ebq.png!web" class="alignCenter" alt="L'histoire entre node.js et macOS" ></p>
(ne me demandez pas pourquoi pas baidu) <span style="font-size: 14px;">OS X</span>
<span style="font-size: 14px;">case-insensitive</span>
Il s'avère que le génial OS X
utilise insensible à la casse
mais pourquoi ? Quel est le but d’une telle conception anti-humaine ?
<span style="font-size: 14px;">node.js</span>
Plus d'explications, allez et venez
Donc, c'est la raison pour laquelle vous ne le faites pas signaler une erreur ? (blâmer node.js
Mais l'affaire n'est pas encore terminée<span style="font-size: 14px;">node.js</span>
Qu'est-ce que ça fait d'avoir un voleur comme père ? <span style="font-size: 14px;">const ParentIncorrect = require('./Parent')</span>
J'en ai vaguement entendu parler. Y a-t-il un cache dans <span style="font-size: 14px;">const Parent = require('./parent')</span>
<span style="font-size: 14px;">node.js</span>
<span style="font-size: 14px;">const ParentIncorrect = require('./Parent')<strong></strong></span>
et
J'ai changé la position et j'ai pensé, serait-il juste de le charger d'abord avec le nom correct ? <span style="font-size: 14px;">ParentIncorrect</span>
Effectivement, <span style="font-size: 14px;">Parent</span>
c'est toujours faux. Vous ne pouvez pas vraiment résoudre le problème en devinant et en faisant semblant<span style="font-size: 14px;">console.log(ParentIncorrect === Parent)</span>
Na Bibi<span style="font-size: 14px;">false</span>
<span style="font-size: 14px;">ParentIncorrect</span>
<span style="font-size: 14px;">Parent</span><span style="font-size: 14px;">node.js</span>
? J'ai donc écrit console.log(ParentIncorrect === Parent)
<span style="font-size: 14px;">clone</span>
, et le résultat était <span style="font-size: 14px;">node.js</span>
false . Donc ce n’est vraiment pas la même chose, donc le problème vient peut-être de la partie introduction ?
Alors l'idée de faire semblant de regarder <span style="font-size: 14px;">node.js</span>
<span style="font-size: 14px;">node.js</span>
<code><span style="font-size: 14px;">require</span> est née (en fait, je ne cherche pas là, problème, je peux enfin le comprendre). Après une longue journée, j'ai finalement clone<code><span style="font-size: 14px;">require</span> et j'ai obtenu un
<span style="font-size: 14px;">src/node_main.cc => src/node.cc => lib/internal/bootstrap_node.js => lib/module.js</span>
Code source (ça a pris beaucoup de temps, tellement lent)
Viens, entrons dans le mystérieux <span style="font-size: 14px;">lib/module.js</span>
<span style="font-size: 14px;">node.js</span>
<code><span style="font-size: 14px;">require</span>
, commençons par elle, mais trouvonsrequire
Le processus de définition demande un peu de patience, je n'entrerai pas dans les détails ici, juste l'ordre de recherchesrc/node_main.cc => cc => lib/internal/bootstrap_node.js => lib/module.js
Je l'ai trouvé, ça y est lib/module.js
, allez droit au but : lib/module.js => require<span style="font-size: 14px;">Module.prototype.require = function(path) {<br/> assert(path, 'missing path');<br/> assert(typeof path === 'string', 'path must be a string');<br/> return Module._load(path, this, /* isMain */ false);<br/>};<br/></span>
好像没什么卵用,对不对?她就调用了另一个方法 <span style="font-size: 14px;">_load</span>
,永不放弃,继续
lib/module.js => _load
<span style="font-size: 14px;">Module._load = function(request, parent, isMain) {<br/> //debug代码,么卵用,跳过<br/> if (parent) {<br/> debug('Module._load REQUEST %s parent: %s', request, parent.id);<br/> }<br/><br/> if (isMain && experimentalModules) {<br/> //...<br/> //...<br/> //这段是给ES module用的,不看了啊<br/> }<br/><br/> //获取模块的完整路径<br/> var filename = Module._resolveFilename(request, parent, isMain);<br/><br/> //缓存在这里啊?好激动有没有?!?终于见到她老人家了<br/> //原来这是这样的,简单的一批,毫无神秘感啊有木有<br/> var cachedModule = Module._cache[filename];<br/> if (cachedModule) {<br/> updateChildren(parent, cachedModule, true);<br/> return cachedModule.exports;<br/> }<br/><br/> //加载native但非内部module的,不看<br/> if (NativeModule.nonInternalExists(filename)) {<br/> debug('load native module %s', request);<br/> return NativeModule.require(filename);<br/> }<br/><br/> //构造全新Module实例了<br/> var module = new Module(filename, parent);<br/><br/> if (isMain) {<br/> process.mainModule = module;<br/> module.id = '.';<br/> }<br/><br/> //先把实例引用加缓存里<br/> Module._cache[filename] = module;<br/><br/> //尝试加载模块了<br/> tryModuleLoad(module, filename);<br/><br/> return module.exports;<br/>};<br/></span>
似乎到这里差不多了,不过我们再深入看看 <span style="font-size: 14px;">tryModuleLoad</span>
lib/module.js => tryModuleLoad
<span style="font-size: 14px;">function tryModuleLoad(module, filename) {<br/> var threw = true;<br/> try {<br/> //加载模块<br/> module.load(filename);<br/> threw = false;<br/> } finally {<br/> //要是加载失败,从缓存里删除<br/> if (threw) {<br/> delete Module._cache[filename];<br/> }<br/> }<br/>}<br/></span>
接下来就是真正的 <span style="font-size: 14px;">load</span>
了,要不我们先停一停?
好了,分析问题的关键在于不忘初心,虽然到目前为止我们前进的比较顺利,也很爽对不对?。但我们的此行的目的并不是爽,好像是有个什么疑惑哦!于是,我们再次梳理下问题:
<span style="font-size: 14px;">son.js</span>
里用首字母大写(不正确)的模块名引用了 <span style="font-size: 14px;">parent.js</span>
<code><span style="font-size: 14px;">test.js</span> 里,引用了两次 <span style="font-size: 14px;">parent.js</span>
,一次用完全一致的模块名;一次用首字母大写的模块名。结果发现 <span style="font-size: 14px;">son instanceof require('./parent') === false</span>
既然没报错的问题前面已经解决了,那么,现在看起来就是加载模块这个部分可能出问题了,那么问题到底是什么?我们怎么验证呢?
这个时候我看到了这么一句话 <span style="font-size: 14px;">var cachedModule = Module._cache[filename];</span>
,文件名是作为缓存的 <span style="font-size: 14px;">key</span>
,来吧,是时候看看 <span style="font-size: 14px;">Module._cache</span>
里存的模块 <span style="font-size: 14px;">key</span>
都是什么牛鬼蛇神了,打出来看看吧,于是我在 <code><span style="font-size: 14px;">test.js</span> 里最后面加了一句 <span style="font-size: 14px;">console.log(Object.keys(require.cache))</span>
,我们看看打出了什么结果
<span style="font-size: 14px;">false<br/>true<br/>[ '/Users/admin/codes/test/index.js',<br/> '/Users/admin/codes/test/Parent.js',<br/> '/Users/admin/codes/test/parent.js',<br/> '/Users/admin/codes/test/son.js' ]<br/></span>
真相已经呼之欲出了, <span style="font-size: 14px;">Module._cache</span>
里真的出现了两个 <span style="font-size: 14px;">[p|P]arent</span>
( <span style="font-size: 14px;">macOS</span>
默认不区分大小写,所以她找到的其实是同一个文件;但 <span style="font-size: 14px;">node.js</span>
当真了,一看文件名不一样,就当成不同模块了),所以最后问题的关键就在于 <span style="font-size: 14px;">son.js</span>
里到底引用时用了哪个名字(上面我们用了首字母大写的 <span style="font-size: 14px;">require('./Parent.js')</span>
),这才导致了 <code><span style="font-size: 14px;">test.js</span> 认贼作父的梗。
如果我们改改 <span style="font-size: 14px;">son.js</span>
,把引用换成 <span style="font-size: 14px;">require('./parEND.js')</span>
,再次执行下 <code><span style="font-size: 14px;">test.js</span> 看看结果如何呢?
<span style="font-size: 14px;">false<br/>false<br/>[ '/Users/haozuo/codes/test/index.js',<br/> '/Users/haozuo/codes/test/Parent.js',<br/> '/Users/haozuo/codes/test/parent.js',<br/> '/Users/haozuo/codes/test/son.js',<br/> '/Users/haozuo/codes/test/parENT.js' ]<br/></span>
没有认贼作父了对不对?再看 <span style="font-size: 14px;">Module._cache</span>
里,原来是 <span style="font-size: 14px;">parENT.js</span>
也被当成一个单独的模块了。
Donc, en supposant que le nom de fichier de votre module comporte <code><span style="font-size: 14px;">n</span>
n caractères, théoriquement, dans <span style="font-size: 14px;">macOS</span>
<span style="font-size: 14px;">macOS</span>
<span style="font-size: 14px;">node.js</span>
Dans un système de fichiers insensible à la casse, vous pouvez utiliser node.js
<span style="font-size: 14px;">2</span>
pour le sortir Maximum <code><span style="font-size: 14px;">n</span>
2 sur
<p>n<span style="font-size: 14px;"></span></p>
alimente les caches pour <span style="font-size: 14px;">macOS</span>
N'est-ce pas misérable ! ? Heureusement, <span style="font-size: 14px;">macOS</span>
Bien que le problème ne soit pas difficile, la détermination et les idées pour explorer le problème sont toujours importantes.
Vous apprendre à utiliser node.js pour créer un processus enfant
Méthode du mode publication-abonnement de Node.jsCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!