mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-16 01:01:38 +00:00
38 lines
20 KiB
HTML
38 lines
20 KiB
HTML
<!DOCTYPE html><html lang="zh-CN" data-default-color-scheme=""auto""><head><meta charset="UTF-8"><link rel="apple-touch-icon" sizes="76x76" href="/images/img/apple-touch-icon.webp"><link rel="icon" type="image/png" href="/images/img/favicon.webp"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,shrink-to-fit=no"><meta http-equiv="x-ua-compatible" content="ie=edge"><meta name="theme-color" content="#9DC8C8"><meta name="description" content=""><meta name="author" content="Defectink"><meta name="keywords" content=""><title>Node.js之旅 - 🍭Defectink</title><link rel="stylesheet" href="https://cdn.defectink.com/static/twitter-bootstrap/4.5.3/css/bootstrap.min.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/github-markdown-css/4.0.0/github-markdown.min.css"><link rel="stylesheet" href="/lib/hint/hint.min.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/highlight.js/10.0.0/styles/github-gist.min.css"><link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css"><link rel="stylesheet" href="https://cdn.defectink.com/static/t/font_1736178_kmeydafke9r.css"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="/css/xfy.css"><script src="/js/utils.js"></script><script src="/js/color-schema.js"></script><meta name="generator" content="Hexo 5.2.0"><link rel="alternate" href="/xml/atom.xml" title="🍭Defectink" type="application/atom+xml"><link rel="alternate" href="/xml/rss.xml" title="🍭Defectink" type="application/rss+xml"></head><body><header style="height:75vh"><nav id="navbar" class="navbar fixed-top navbar-expand-lg navbar-dark scrolling-navbar"><div class="container"><a class="navbar-brand" href="/"> <strong>🍭Defectink</strong> </a> <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><div class="animated-icon"><span></span><span></span><span></span></div></button><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav ml-auto text-center"><li class="nav-item"><a class="nav-link" href="/">🏠 首页</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">📕 索引</a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item" href="/categories/">🎁 分类</a> <a class="dropdown-item" href="/tags/">🎐 标签</a></div></li><li class="nav-item"><a class="nav-link" href="/archives/">📂 归档</a></li><li class="nav-item"><a class="nav-link" href="/about/">🎃 关于</a></li><li class="nav-item"><a class="nav-link" href="/links/">🙆♀️ 小伙伴</a></li><li class="nav-item"><a class="nav-link" href="/pgp/">🔐 PGP</a></li><li class="nav-item" id="search-btn"><a class="nav-link" data-toggle="modal" data-target="#modalSearch"> <i class="iconfont icon-search"></i> </a></li><li class="nav-item" id="color-toggle-btn"><a class="nav-link" href="javascript:"> <i class="iconfont icon-dark" id="color-toggle-icon"></i> </a></li></ul></div></div></nav><div class="banner intro-2" id="background" parallax="true" style="background:url(/images/img/post.webp) no-repeat center center;background-size:cover"><div class="full-bg-img"><div class="mask flex-center" style="background-color:rgba(0,0,0,.3)"><div class="container page-header text-center fade-in-up"><span class="h2" id="subtitle"></span><div class="mt-3"><span class="post-meta mr-2"><i class="iconfont icon-author" aria-hidden="true"></i> Defectink</span><span class="post-meta"><i class="iconfont icon-date-fill" aria-hidden="true"></i> <time datetime="2020-09-03 16:09" pubdate>2020年9月3日 下午</time></span></div><div class="mt-1"><span class="post-meta mr-2"><i class="iconfont icon-chart"></i> 1.6k 字</span><span class="post-meta mr-2"><i class="iconfont icon-clock-fill"></i> 18 分钟</span></div></div></div></div></div></header><main><div class="container-fluid"><div class="row"><div class="d-none d-lg-block col-lg-2"></div><div class="col-lg-8 nopadding-md"><div class="container nopadding-md" id="board-ctn"><div class="py-5" id="board"><article class="post-content mx-auto" id="post"><h1 style="display:none">Node.js之旅</h1><p class="note note-info">本文最后水于:2020年11月2日 凌晨</p><div class="markdown-body" id="post-body"><blockquote><p>Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.</p></blockquote><p>Node.js不仅仅是服务器上的JavaScript。</p><p><img src="../images/Node.js%E4%B9%8B%E6%97%85/2020-09-03-14-54-53.webp" srcset="/images/img/loading.gif"></p><h2 id="并不熟悉的JavaScript"><a href="#并不熟悉的JavaScript" class="headerlink" title="并不熟悉的JavaScript"></a>并不熟悉的JavaScript</h2><p>虽然说Node直接般来了个V8来运行JavaScript,但它毕竟不运行在浏览器上,并且是由事件驱动的异步程序,它的本来的目的就是用来搭建高性能的Web服务器。在极少情况下,编写的 JavaScript 代码没有按期望的方式运行。</p><p>在客户端的运行环境下,只要是在同一个浏览器窗口运行的JS环境就属于同一个全局环境。无论是在哪里引入的JS文件,都属于同一个运行环境,全局变量能够正常工作,例如有两个js被引入:</p><pre><code class="hljs html"><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"a.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
|
||
<span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"b.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre><p>他们分别有一段代码:</p><pre><code class="hljs js"><span class="hljs-comment">// a.js</span>
|
||
<span class="hljs-keyword">let</span> a = <span class="hljs-string">'xxxxxfy!'</span>;
|
||
|
||
<span class="hljs-comment">// b.js</span>
|
||
alert(a);</code></pre><p>正常情况下全局变量<code>a</code>是可以被正常访问的,而在node中,a.js和b.js分别是两个文件,不做其他操作的情况下,他们分别是两个全局变量。</p><h2 id="基础架构"><a href="#基础架构" class="headerlink" title="基础架构"></a>基础架构</h2><p>Node 运行时的基础架构由两大组件构成:</p><ul><li>JavaScript 引擎</li><li>非阻塞 I/O 库</li></ul><h3 id="JavaScript引擎"><a href="#JavaScript引擎" class="headerlink" title="JavaScript引擎"></a>JavaScript引擎</h3><p>众所周知,node使用的是Chrome大排自吸V8,它可以运行任何JS代码。启动时,它会启动一个V8的引擎实例,且node可以充分的利用这个引擎实例。</p><p>V8可嵌入(/绑定)到任何C++程序中,。这意味着,除了纯 JavaScript 库外,还可以扩展 V8 来创建全新的函数(或函数模板),方法是将其与 V8 绑定在一起。并且node还支持使用编译好的二进制的C++程序。</p><h3 id="事件循环"><a href="#事件循环" class="headerlink" title="事件循环"></a>事件循环</h3><p>JavaScript是一门单线程的语言,无论换到什么地方运行,它也是单线程语言。单线程语言面临的最大的问题就是阻塞,在前面的代码没有被执行完,后面的代码都将处于等待状态。</p><p>node使用<a target="_blank" rel="noopener" href="http://libuv.org/">libuv</a>来实现事件循环。要使用事件循环可以使用异步API,可将回调函数作为参数传递到该 API 函数,在事件循环期间会执行该回调函数。node异步编程的直接体现就是回调函数。异步编程基于回调函数来实现,但不能说是使用了回调后程序就异步化了。Node 所有 API 都支持回调函数。</p><pre><code class="hljs smali"> ┌───────────────────────────┐
|
||
┌─>│ timers │
|
||
│ └─────────────┬─────────────┘
|
||
│ ┌─────────────┴─────────────┐
|
||
│ │ pending callbacks │
|
||
│ └─────────────┬─────────────┘
|
||
│ ┌─────────────┴─────────────┐
|
||
│ │ idle, prepare │
|
||
│ └─────────────┬─────────────┘ ┌───────────────┐
|
||
│ ┌─────────────┴─────────────┐ │ incoming: │
|
||
│ │ poll │<─────┤ connections, │
|
||
│ └─────────────┬─────────────┘ │ data, etc. │
|
||
│ ┌─────────────┴─────────────┐ └───────────────┘
|
||
│ │ <span class="hljs-built_in"> check </span> │
|
||
│ └─────────────┬─────────────┘
|
||
│ ┌─────────────┴─────────────┐
|
||
└──┤ close callbacks │
|
||
└───────────────────────────┘</code></pre><p>例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。</p><p>事件循环包含多个调用回调函数的阶段:</p><ul><li>计时器阶段:将运行 setInterval() 和 setTimeout() 过期计时器回调函数</li><li>轮询阶段:将轮询操作系统以查看是否完成了所有 I/O 操作,如果已完成,将运行回调函数</li><li>检查阶段:将运行 setImmediate() 回调函数</li></ul><p>一个常见的误区是,认为 V8 和事件循环回调函数在不同线程上运行。但事实并非如此。V8 在同一个线程上运行所有 JavaScript 代码。</p><h2 id="非阻塞I-O"><a href="#非阻塞I-O" class="headerlink" title="非阻塞I/O"></a>非阻塞I/O</h2><p>已经简单的了解过node基于v8的单线程来使用回调函数实现异步编程,从而达到高性能与高并发。</p><h3 id="异步I-O"><a href="#异步I-O" class="headerlink" title="异步I/O"></a>异步I/O</h3><p>异步I/O能够大大的提升程序的工作效率,且不会影响剩下的代码执行。</p><h4 id="同步读取文件"><a href="#同步读取文件" class="headerlink" title="同步读取文件"></a>同步读取文件</h4><p>首先来看下同步读取文件</p><pre><code class="hljs js"><span class="hljs-keyword">let</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
|
||
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'starting process...'</span>);
|
||
<span class="hljs-keyword">let</span> data = fs.readFileSync(<span class="hljs-string">'test.txt'</span>);
|
||
<span class="hljs-built_in">console</span>.log(data);
|
||
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'the end'</span>);</code></pre><p>同步读取文件会按照从上到下的顺序来执行代码,到遇到读取I/O时,剩下的代码将处于等待状态。并且在读取I/O时遇到错误(例如文件不存在),将会直接返回错误,剩下的代码将不执行完。</p><h4 id="异步读取文件"><a href="#异步读取文件" class="headerlink" title="异步读取文件"></a>异步读取文件</h4><pre><code class="hljs js"><span class="hljs-keyword">let</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
|
||
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'starting process...'</span>);
|
||
fs.readFile(<span class="hljs-string">'test.txt'</span>, <span class="hljs-function">(<span class="hljs-params">err, data</span>) =></span> {
|
||
<span class="hljs-keyword">if</span> (err) {
|
||
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'something was wrong: '</span> + err);
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-built_in">console</span>.log(data);
|
||
}
|
||
})
|
||
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'the end'</span>);</code></pre><p>异步读取文件调用了回调函数,它设置了一个事件循环,在等待读取I/O的同时,将继续执行剩下的代码。当文件读取完成之后,将会返回回调函数,并输出结果。并且当读取文件遇到错误时,在等待读取期间执行的代码将正常执行。</p><p>异步的结果看起来像是这样的:</p><pre><code class="hljs angelscript">starting process...
|
||
the end
|
||
<Buffer <span class="hljs-number">64</span> <span class="hljs-number">66</span> <span class="hljs-number">6</span>a <span class="hljs-number">61</span> <span class="hljs-number">73</span>></code></pre><p>在等待其读取<code>test.txt</code>的期间,JS将剩下的<code>console.log</code>语句先执行了。</p><h3 id="同步I-O"><a href="#同步I-O" class="headerlink" title="同步I/O"></a>同步I/O</h3><p>node的设计理念就是使用异步编程,使用阻塞编程可无法写出一个高性能的web服务器。</p><p>但这不代表着同步I/O就一无是处,在某些情况下,同步 I/O 通常比异步 I/O 更快,原因在于设置和使用回调函数、轮询操作系统来获取 I/O 状态等操作都涉及到一定的开销。</p><p>如果需要写一个一次性的使用程序,仅用于处理一个文件,从命令行中启动 Node,并向其传递 JavaScript 实用程序的文件名。此时,该实用程序是唯一运行的程序,因此,即使它阻塞了 V8 线程,也没有任何影响。在此情况下,适合使用同步 I/O。</p><p>只要是谨慎使用同步 Node API 调用,就不会出现什么问题。</p><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><ul><li>V8是有八个气缸的V型发动机.</li><li>JavaScript是单线程语言,它通过V8 引擎提供的异步执行回调接口实现了异步编程。</li></ul><p>全文均是笔记</p><ul><li><a target="_blank" rel="noopener" href="https://developer.ibm.com/zh/tutorials/learn-nodejs-tour-node/">Node.js 之旅</a></li><li><a target="_blank" rel="noopener" href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/">The Node.js Event Loop</a></li><li><a target="_blank" rel="noopener" href="https://www.runoob.com/nodejs/nodejs-callback.html">Node.js 回调函数</a></li><li><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/V8%E5%8F%91%E5%8A%A8%E6%9C%BA">V8发动机</a></li></ul></div><hr><div><div class="post-metas mb-3"><div class="post-meta mr-3"><i class="iconfont icon-category"></i> <a class="hover-with-bg" href="/categories/%E7%AC%94%E8%AE%B0/">笔记</a></div><div class="post-meta"><i class="iconfont icon-tags"></i> <a class="hover-with-bg" href="/tags/JavaScript/">JavaScript</a> <a class="hover-with-bg" href="/tags/Node/">Node</a></div></div><p class="note note-warning"><a target="_blank" href="https://zh.wikipedia.org/wiki/Wikipedia:CC_BY-SA_3.0%E5%8D%8F%E8%AE%AE%E6%96%87%E6%9C%AC" rel="nofollow noopener noopener">CC BY-SA 3.0❤</a></p><div class="post-prevnext row"><article class="post-prev col-6"><a href="/defect/Vue-js-get-started.html"><i class="iconfont icon-arrowleft"></i> <span class="hidden-mobile">Vue.js-起步!</span> <span class="visible-mobile">上一篇</span></a></article><article class="post-next col-6"><a href="/defect/irc-getting-started.html"><span class="hidden-mobile">入坑IRC</span> <span class="visible-mobile">下一篇</span><i class="iconfont icon-arrowright"></i></a></article></div></div><article class="comments" id="comments"><div id="vcomments"></div><script type="text/javascript">function loadValine(){addScript("https://cdn.defectink.com/static/valine/1.4.14/Valine.min.js",function(){new Valine({el:"#vcomments",app_id:"dD9t7mcIBVzJWag5ez6GPy2v-MdYXbMMI",app_key:"bWG6pmKsEscrH4JjrpNNAAy6",placeholder:"嘤嘤嘤???",path:window.location.pathname,avatar:"retro",meta:["nick","mail","link"],pageSize:"10",lang:"zh-CN",highlight:!0,recordIP:!1,serverURLs:""})})}waitElementVisible("vcomments",loadValine)</script><noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments powered by Valine.</a></noscript></article></article></div></div></div><div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn"><div id="toc"><p class="toc-header"><i class="iconfont icon-list"></i> 目录</p><div id="tocbot"></div></div></div></div></div></main><a id="scroll-top-button" href="#" role="button"><i class="iconfont icon-arrowup" aria-hidden="true"></i></a><div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true"><div class="modal-dialog modal-dialog-scrollable modal-lg" role="document"><div class="modal-content"><div class="modal-header text-center"><h4 class="modal-title w-100 font-weight-bold">搜索</h4><button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button></div><div class="modal-body mx-3"><div class="md-form mb-5"><input type="text" id="local-search-input" class="form-control validate"> <label data-error="x" data-success="v" for="local-search-input">关键词</label></div><div class="list-group" id="local-search-result"></div></div></div></div></div><footer class="text-center mt-5 py-3"><div class="footer-content"><a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a><i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a></div><div class="beian"><a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">皖ICP备17017808号</a></div></footer><script src="https://cdn.defectink.com/static/jquery/3.4.1/jquery.min.js"></script><script src="https://cdn.defectink.com/static/twitter-bootstrap/4.5.3/js/bootstrap.min.js"></script><script src="/js/debouncer.js"></script><script src="/js/main.js"></script><script src="/js/lazyload.js"></script><script defer="defer" src="https://cdn.defectink.com/static/clipboard.js/2.0.6/clipboard.min.js"></script><script src="/js/clipboard-use.js"></script><script src="/js/xfy.js"></script><script src="https://cdn.defectink.com/static/tocbot/4.11.1/tocbot.min.js"></script><script>$(document).ready(function(){var t=$("#board-ctn").offset().top;tocbot.init({tocSelector:"#tocbot",contentSelector:"#post-body",headingSelector:"h1,h2,h3,h4,h5,h6",linkClass:"tocbot-link",activeLinkClass:"tocbot-active-link",listClass:"tocbot-list",isCollapsedClass:"tocbot-is-collapsed",collapsibleClass:"tocbot-is-collapsible",collapseDepth:3,scrollSmooth:!0,headingsOffset:-t}),0<$(".toc-list-item").length&&$("#toc").css("visibility","visible")})</script><script src="https://cdn.defectink.com/static/typed.js/2.0.11/typed.min.js"></script><script>var typed=new Typed("#subtitle",{strings:[" ","Node.js之旅 "],cursorChar:"❤",typeSpeed:70,loop:!1});typed.stop(),$(document).ready(function(){$(".typed-cursor").addClass("h2"),typed.start()})</script><script src="/js/local-search.js"></script><script>var path="/xml/local-search.xml",inputArea=document.querySelector("#local-search-input");inputArea.onclick=function(){searchFunc(path,"local-search-input","local-search-result"),this.onclick=null}</script><script src="https://cdn.defectink.com/static/fancybox/3.5.7/jquery.fancybox.min.js"></script><link rel="stylesheet" href="https://cdn.defectink.com/static/fancybox/3.5.7/jquery.fancybox.min.css"><script>$("#post img:not(.no-zoom img, img[no-zoom]), img[zoom]").each(function(){var t=document.createElement("a");$(t).attr("data-fancybox","images"),$(t).attr("href",$(this).attr("src")),$(this).wrap(t)})</script><script src="https://cdn.defectink.com/static/mermaid/8.5.0/mermaid.min.js"></script><script>window.mermaid&&mermaid.initialize({theme:"default"})</script></body></html> |