Node.js自学完全总结
<div><h3>零、什么是Node.js?</h3>
<p>引用Node.js官方网站的解释如下:</p>
<blockquote>
<p>Node.js® is a JavaScript <strong>runtime</strong> built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.</p>
</blockquote>
<p>翻译成中文就是:</p>
<blockquote>
<p>Node.js 是一个基于 Chrome V8 引擎的 JavaScript <strong>运行环境</strong>。<br>
Node.js 使用了一个<strong>事件驱动</strong>、<strong>非阻塞式 I/O</strong> 的模型,使其轻量又高效。</p>
</blockquote>
<h5>1、 运行环境(Runtime)</h5>
<p>如果做一个类比,Node.js与JavaScript关系,就像JDK(Java Development Kit)与Java的关系。<br>
总的来说,Node.js不是一门语言,而是用来进行Web开发的Runtime。</p>
<h5>2、事件驱动(Event-driven)</h5>
<p>在前端web开发中比较常见的事件驱动例子是,给一个按钮绑定一个事件处理程序,这个事件处理程序就是事件驱动的,JavaScript进程并不知道什么时候调用它,点击按钮,触发Click事件,此时主程序得到相应的通知,就知道调用绑定的的事件处理程序了。<br>
因为Node.js是JavaScript的Runtime,所以天然就可以使用这种模式通知主进程的I/O 完成。</p>
<h5>3、非阻塞式 I/O(Non-blocking I/O)</h5>
<p>阻塞:I/O 时进程休眠等待 I/O 完成后进行下一步<br>
非阻塞:I/O 时函数立即返回,进程不等待I/O 完成</p>
<h3>一、Node.js 究竟好在哪里?</h3>
<h5>1、为什么偏爱Node.js</h5>
<p>① 前端需求变得重要、职责范围变大,统一开发体验<br>
② 在处理高并发、I/O 密集型场景性能优势明显</p>
<p>Node.js 使用了事件驱动和非阻塞的 I/O 模型,使 Node 轻量高效,非常适合 I/O 密集的 Web 场景。</p>
<p><strong>CPU密集型VSI/O密集型</strong><br>
CPU密集型:计算等逻辑判断的操作,如:压缩、解压、加密和解密等。<br>
I/O 密集型:存取设备,网络设施的读取操作,如:文件的存取,http等网络操作,数据库操作等。</p>
<h5>2、Web常见场景</h5>
<p>① 静态资源读取<br>
html,css,js等文件的读取<br>
② 数据库操作<br>
把数据存取到物理设磁盘或内存中<br>
③ 渲染页面<br>
读取模板文件,根据数据生成html</p>
<h5>3、高并发应对之道</h5>
<p>高并发,简而言之就是单位时间内访问量特别大。</p>
<p>对应生活中的场景,一家菜馆做菜招待顾客,老板刚开始就雇了一个厨师,做菜好吃不贵,顾客很多,顾客排好一条队,然后顾客选好菜,厨师拿到菜单开始做菜,做好菜,给顾客端上来,再招待下个顾客。</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1660" data-height="252"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082412253-1046890410.jpg" alt=""></div>
</div>
<div class="image-caption">一个厨师应对若干顾客</div>
</div>
<p>客人增多,一个厨师忙不过来了,老板于是又招了2个厨师,这样顾客可以排3条队,快了很多。</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1710" data-height="358"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082424948-2079339472.jpg" alt=""></div>
</div>
<div class="image-caption">多个厨师应对若干顾客</div>
</div>
<p>随着菜馆名气增大,顾客越来越多,老板本想再用之前的方法多招几个厨师,但是老板想,多招厨师好像不太划算,有些厨师做饭快,有些做饭慢,经过调查,老板发现做饭快2倍的厨师只需要花费原来厨师工资的1.5倍,于是精明的老板炒掉了原来的3个厨师,招来了比原来厨师做饭速度快2倍的另外3个厨师,菜馆比之前运转的更好了。</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1552" data-height="344"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082443790-25891693.jpg" alt=""></div>
</div>
<div class="image-caption">多个速度快的厨师应对若干顾客</div>
</div>
<p>回到Web开发场景,厨师就是物理服务器,应对高并发的方法如下:<strong>① 增加机器数</strong><br>
机器多了,流量还是一样的大,通过Nginx负载均衡分到不同的机器上处理<br>
<strong>② 增加每台机器的CPU数——多核</strong><br>
单位机器,核数增多,运算能力增强了</p>
<h5>4、进程与线程</h5>
<p>进程在百度百科中的解释如下:</p>
<blockquote>
<p>进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。</p>
</blockquote>
<p>换成正常的人话就是:电脑桌面的程序,如QQ音乐,当我们双击图标时,实际上是把这个程序加载到内存中执行,我们称这个执行中的程序就是进程,操作系统都是用进程作为基本单位进行分配和调度的。</p>
<blockquote>
<p>多进程:启动多个进程,多个进程可以一块执行多个任务。</p>
</blockquote>
<blockquote>
<p>线程,进程内一个相对独立的、可调度的执行单元,与同属一个进程的线程共享进程的资源。</p>
</blockquote>
<blockquote>
<p>多线程,启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。</p>
</blockquote>
<h5>5、Node.js工作模型</h5>
<p>传统的server处理请求(如多线程高并发模式的Apache)对应生活中的场景,如下:<br>
一个老板开了一家饭店,不同于之前那个菜馆,这家的每个厨师配备了一个服务员,专门负责点菜,然后把菜单给厨师,厨师负责做菜,做完后给服务员,服务员端给客人,然后再接待顾客队伍中的下一个。</p>
<p>如果这个饭店是Web的话,点菜这个动作很快,相当于CPU的运算,如访问一个静态资源,CPU运算后知道是哪个文件了,去相应盘读取,类似于厨师做饭,是一个相对较慢的阻塞I/O操作,当顾客很多时候就相当于高并发了。忙不过来的时候,可以选择增加厨师数量和服务员数量,即并发多进程处理多个请求的概念。</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1704" data-height="546"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082525866-1811653665.jpg" alt=""></div>
</div>
<div class="image-caption">一个服务员每次只接待一个顾客</div>
</div>
<p>但是这个饭店老板慢慢发现,增加服务员和厨师的同时,饭店的空间是有限的,慢慢的变得拥挤(阻塞),而且更为头疼的是另一个问题:服务员太悠闲了,2分钟就把点菜的事干完了,厨师做菜10分钟,那他就有8分钟在那干等着,没事干,因为厨师没把菜做完给他,他也不能接待下一个顾客。</p>
<p>同样类似于Apache开发web时候,CPU分配的最大进程数是有限的,并不能没完没了的分配进程的,并发到一定数目的时候,必须得排队(阻塞)了,更大的问题是,<strong>CPU处理的速度远远快于I/O</strong>,在Web场景中,CPU运用场景很少,大头都在I/O上,CPU大部分进程情况下都是在等待,等待I/O,CPU的资源被浪费掉了,相当于饭店的服务员一直干等着没事干。</p>
<p>Node.js很好的解决了上面的问题👆👆👆,来看下Node.js对应的生活中的场景,如下:</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1624" data-height="530"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082554426-1301694926.jpg" alt=""></div>
</div>
<div class="image-caption">一个服务员每次接待多个顾客</div>
</div>
<p>另一个老板也开了一家饭店,这家饭店只雇佣了一个服务员,这个服务员接待所有的顾客,顾客来了依次点菜,点完菜拿个号找地方坐着去了,然后服务员把菜单交给厨师们,然后再去给下一波客人点菜下单,等后厨什么时候说,服务员几号的菜好了,然后服务员端好菜给制定号码的顾客,无论哪个顾客来了立刻相应,<strong>厨师一直做菜,服务员一直接单</strong>,顾客的体验也比上一家要好,不用等到上一个顾客拿到菜才开始点单等待。对应Web体验就是:一直在那转圈等待,要比直接显示连不上要好。</p>
<p>同样在Node.js中,用户(顾客)发来请求,有一个主进程(服务员),对应有一个事件轮询(Event Loop),来处理用户的各种请求过来的进程(菜单),如qq音乐(小葱拌豆腐),Photoshop(鱼香肉丝)等,然后给Worker threads即多线程(厨师)的去处理,处理完后完成回调(上菜),CPU的利用率达到最大。<strong>在Node.js中,一个CPU上只开一个进程,一个进程里只有一个线程</strong>。</p>
<div class="image-package">
<div class="image-container">
<div class="image-container-fill"> </div>
<div class="image-view" data-width="1346" data-height="768"><img src="https://img2018.cnblogs.com/blog/48590/201905/48590-20190531082638402-75835234.jpg" alt=""></div>
</div>
<div class="image-caption">Node.js工作模型(图片源于网络)</div>
</div>
<h5>6、Node.js单线程</h5>
<p>Node.js单线程指的是,一个CPU上只开一个进程,一个进程里只有一个线程。但这个单线程只是针对<strong>主进程</strong>,I/O 等其它各种异步操作都是操作系统底层在多线程调度的 。Node.js就是主进程发起一个请求,请求交给I/O 之后,是由操作系统底层多进程多线程进行调度,然后达到最佳性能。</p>
<p>Node.js是单线程的,但是不要理解为它做所有事都是单线程的,有一部分不是自己做的,而是交给操作系统做的,它只负责单进程的在那<strong>听</strong>,操作系统好了,就告诉它单进程的做另外的事情,操作系统怎么处理I/O,它不管。</p>
<p><strong>单线程并不就是单进程</strong>,Node.js有个多核处理模块叫<strong>cluster</strong>,专门用来处理多CPU,CPU如果有8个核,用了cluster之后,Node.js就启了8个进程,不会浪费CPU的能力。</p>
<h5>7、Node.js能干嘛</h5>
<ul>
<li>Web Server</li>
<li>本地代码编译构建(grunt、babel等工具都是基于Node.js开发的)</li>
<li>实用工具的开发(爬虫等)</li>
</ul>
<h3>三、Node.js的基础API</h3>
<h5>1、path(路径)</h5>
<p><code>path</code> 模块提供了一些工具函数,用于处理文件与目录的路径。可以通过以下方式使用:<br>
<code>const path = require('path');</code><br>
<code>path</code>常用方法:<br>
① <code>path.normalize(path)</code><br>
会规范化给定的 path,并解析 '..' 和 '.' 片段,如:</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const { normalize } = <span class="hljs-built_in">require(<span class="hljs-string">'path');
<span class="hljs-built_in">console.log(normalize.(<span class="hljs-string">'/usr///local/bin')); <span class="hljs-comment">///usr/local/bin
<span class="hljs-built_in">console.log(normalize.(<span class="hljs-string">'/usr//local/../bin'));<span class="hljs-comment">///usr/bin
<span class="hljs-comment">/*或者这样写:
const path = require('path');
console.log(path.normalize.('/usr///local/bin'));
*/
</span></span></span></span></span></span></span></span></span></span></code></pre>
<p>② <code>path.join([...paths])</code><br>
使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径,也能解析 '..' 和 '.' ,如:</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const { join } = <span class="hljs-built_in">require(<span class="hljs-string">'path');
<span class="hljs-built_in">console.log(join.(<span class="hljs-string">'/usr', <span class="hljs-string">'local', <span class="hljs-string">'bin/')); <span class="hljs-comment">///usr/local/bin
<span class="hljs-built_in">console.log(join.(<span class="hljs-string">'/usr', <span class="hljs-string">'../local', <span class="hljs-string">'bin/'));<span class="hljs-comment">///usr/bin
</span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>③ <code>path.resolve([...paths])</code><br>
会把一个路径或路径片段的序列解析为一个绝对路径,如:</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const { resolve } = <span class="hljs-built_in">require(<span class="hljs-string">'path');
<span class="hljs-built_in">console.log(resolve.(<span class="hljs-string">'./')); <span class="hljs-comment">///Users/peng/Desktop 返回当前路径的绝对路径
</span></span></span></span></span></span></code></pre>
<p>④ <code>path.basename(path[, ext])</code><br>
返回文件名<br>
<code>path.dirname(path)</code> 返回所在文件夹名<br>
<code>path.extname(path)</code> 返回扩展名</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const { basename, dirname, extname } = <span class="hljs-built_in">require(<span class="hljs-string">'path');
<span class="hljs-keyword">const filePath = <span class="hljs-string">'/usr/local/bin/test.html';
<span class="hljs-built_in">console.log(basename.(filePath)); <span class="hljs-comment">//test.html
<span class="hljs-built_in">console.log(dirname.(filePath)); <span class="hljs-comment">///usr/local/bin
<span class="hljs-built_in">console.log(extname.(filePath)); <span class="hljs-comment">//.html
</span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>⑤ <code>path.parse(path)</code><br>
返回一个对象,对象的属性表示 path 的元素<br>
<code>path.format()</code> 会从一个对象返回一个路径字符串。 与 <code>path.parse()</code>方法相反</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const { parse, format } = <span class="hljs-built_in">require(<span class="hljs-string">'path');
<span class="hljs-keyword">const filePath = <span class="hljs-string">'/usr/local/bin/test.html';
<span class="hljs-keyword">const ret = parse(filePath);
<span class="hljs-built_in">console.log(ret);
<span class="hljs-comment">/*
{ root: '/',
dir: '/usr/local/bin',
base: 'test.html',
ext: '.html',
name: 'test' }
*/
<span class="hljs-built_in">console.log(format(ret));<span class="hljs-comment">// /usr/local/bin/test.html
</span></span></span></span></span></span></span></span></span></span></code></pre>
<p>另外:<br>
<code>__dirname</code>、<code>__filename</code>总是返回文件的绝对路径<br>
<code>process.cwd()</code>总是返回执行node命令所在的文件夹</p>
<h5>2、Buffer (缓冲)</h5>
<p><code>Buffer</code> 类被引入作为 Node.js API 的一部分,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流。</p>
<p>Buffer 类的实例类似于整数数组,但 Buffer 的大小是固定的、且在 V8 堆外分配物理内存。 Buffer 的大小在被创建时确定,且无法调整。</p>
<p>Buffer 类在 Node.js 中是一个全局变量(global),因此无需使用<code>require('buffer').Buffer</code>。</p>
<p>常用方法:<br>
① <code>Buffer.byteLength()</code><br>
返回一个字符串的实际字节长度。 这与 String.prototype.length不同,因为那返回字符串的<strong>字符</strong>数。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">console.log(Buffer.byteLength(<span class="hljs-string">'test')); <span class="hljs-comment">// 4
<span class="hljs-built_in">console.log(Buffer.byteLength(<span class="hljs-string">'中国'));<span class="hljs-comment">// 6
</span></span></span></span></span></span></code></pre>
<p>② <code>Buffer.from(array)</code><br>
通过一个八位字节的 array 创建一个新的 Buffer ,如果 array 不是一个数组,则抛出 TypeError 错误。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">console.log(Buffer.from([<span class="hljs-number">1, <span class="hljs-number">2, <span class="hljs-number">3]));<span class="hljs-comment">// <Buffer 01 02 03>
</span></span></span></span></span></code></pre>
<p>③ <code>Buffer.isBuffer(obj)</code><br>
如果 obj 是一个 Buffer 则返回 true ,否则返回 false</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-built_in">console.log(Buffer.isBuffer({ <span class="hljs-string">'a': <span class="hljs-number">1 })); <span class="hljs-comment">// false
<span class="hljs-built_in">console.log(Buffer.isBuffer(Buffer.from([<span class="hljs-number">1, <span class="hljs-number">2, <span class="hljs-number">3])));<span class="hljs-comment">// true
</span></span></span></span></span></span></span></span></span></code></pre>
<p>④ <code>Buffer.concat(list)</code><br>
如果 obj 是一个 Buffer 则返回 true ,否则返回 false</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const buf1 = Buffer.from(<span class="hljs-string">'hello ');
<span class="hljs-keyword">const buf2 = Buffer.from(<span class="hljs-string">'world');
<span class="hljs-keyword">const buf = Buffer.concat();
<span class="hljs-built_in">console.log(buf.toString()); <span class="hljs-comment">// hello world
</span></span></span></span></span></span></span></code></pre>
<p>常用属性:<br>
① <code>buf.length</code> 长度<br>
<code>buf.toString()</code> 转为字符串<br>
<code>buf.fill()</code> 填充<br>
<code>buf.equals()</code> 判断是否相等<br>
<code>buf.indexOf()</code> 是否包含,如果包含返回位置值,不包含返回-1</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const buf = Buffer.from(<span class="hljs-string">'hello world');
<span class="hljs-keyword">const buf2 = Buffer.from(<span class="hljs-string">'hello world!');
<span class="hljs-built_in">console.log(buf.length); <span class="hljs-comment">// 15
<span class="hljs-built_in">console.log(buf.toString()); <span class="hljs-comment">// hello world
<span class="hljs-built_in">console.log(buf.fill(<span class="hljs-number">10, <span class="hljs-number">2, <span class="hljs-number">6));<span class="hljs-comment">// <Buffer 68 65 0a 0a 0a 0a 77 6f 72 6c 64> 这里从第3个到第6个都被替换成了0a,a就是16进制的数字10
<span class="hljs-built_in">console.log(buf.equals(buf2));<span class="hljs-comment">// false
<span class="hljs-built_in">console.log(buf.indexOf(<span class="hljs-string">'h'));<span class="hljs-comment">// 0
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<h5>3、events(事件)</h5>
<p>大多数 Node.js 核心 API 都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器)。</p>
<p>所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。</p>
<p>官网例子:一个绑定了一个监听器的 EventEmitter 实例。 eventEmitter.on() 方法用于注册监听器,eventEmitter.emit() 方法用于触发事件。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const EventEmitter = <span class="hljs-built_in">require(<span class="hljs-string">'events');
<span class="hljs-class"><span class="hljs-keyword">class <span class="hljs-title">CustomEvent <span class="hljs-keyword">extends <span class="hljs-title">EventEmitter {}
<span class="hljs-keyword">const myEmitter = <span class="hljs-keyword">new CustomEvent();
myEmitter.on(<span class="hljs-string">'error', err => {
<span class="hljs-built_in">console.log(err);
})
myEmitter.emit(<span class="hljs-string">'error', <span class="hljs-keyword">new <span class="hljs-built_in">Error(<span class="hljs-string">'This is an error!'));
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>当有一个错误的时候,会显示<code>Error: This is an error!</code>,然后显示具体错误内容。</p>
<h5>4、fs(文件系统)</h5>
<p>通过 require('fs') 使用该模块。 所有的方法都有<strong>异步和同步</strong>的形式。</p>
<p>异步方法的最后一个参数都是一个<strong>回调函数</strong>。 传给回调函数的参数取决于具体方法,但回调函数的第一个参数都会保留给异常。 如果操作成功完成,则第一个参数会是 null 或 undefined。</p>
<p>常用方法如下:<br>
① <code>fs.readFile(path[, options], callback)</code><br>
异步地读取一个文件的全部内容</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.readFile(<span class="hljs-string">'./test.txt', (err, data) => {
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(data);
});
</span></span></span></span></span></span></span></code></pre>
<p>此时如果test.txt文件内容只有一个字母a,那么打印出来的就是<code><Buffer 61></code><br>
回调有两个参数 (err, data),其中 data 是文件的内容。如果未指定字符编码,则返回原始的 buffer。<br>
指定编码格式后,就会按照编码格式打印文件内容:</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.readFile(<span class="hljs-string">'./test.txt', <span class="hljs-string">'utf-8',(err, data) => {
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(data);
});
</span></span></span></span></span></span></span></span></code></pre>
<p>此时如果test.txt文件内容只有一个字母a,那么打印出来的就是<code>a</code></p>
<p>② <code>fs.writeFile(file, data[, options], callback)</code><br>
异步地写入数据到文件,如果文件已经存在,则替代文件。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.writeFile(<span class="hljs-string">'message.txt', <span class="hljs-string">'Hello Node.js', (err) => {
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(<span class="hljs-string">'The file has been saved!');
});
</span></span></span></span></span></span></span></span></span></code></pre>
<p>③ <code>fs.stat(path,callback)</code><br>
可用来判断一个文件是否存在<br>
回调有两个参数 (err, stats),其中 stats是一个 fs.Stats对象。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.stat(<span class="hljs-string">'./message.txt', (err, stats)=>{
<span class="hljs-keyword">if (err){
<span class="hljs-built_in">console.log(<span class="hljs-string">'文件不存在');
<span class="hljs-keyword">return;
};
<span class="hljs-built_in">console.log(stats.isFile()); <span class="hljs-comment">// true判断是否是一个文件
<span class="hljs-built_in">console.log(stats.isDirectory());<span class="hljs-comment">// false判断是否是一个文件夹
});
</span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
<p>④ <code>fs.rename(oldPath, newPath, callback)</code><br>
用来修改文件名</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.rename(<span class="hljs-string">'./message.txt', <span class="hljs-string">'m.txt', err=>{
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(<span class="hljs-string">'修改成功!');
})
</span></span></span></span></span></span></span></span></span></code></pre>
<p>⑤ <code>fs.unlink(path, callback)</code><br>
删除文件</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.unlink(<span class="hljs-string">'./m.txt', err=>{
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(<span class="hljs-string">'删除成功!');
})
</span></span></span></span></span></span></span></span></code></pre>
<p>⑥ <code>fs.readdir(path[, options], callback)</code><br>
读取指定路径下的所有文件</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.readdir(<span class="hljs-string">'./', (err, files)=>{
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(files);
<span class="hljs-comment">/*
[ '.DS_Store',
'node_modules',
'package.json',
'test.js',
'test.txt' ]
*/
})
</span></span></span></span></span></span></span></span></code></pre>
<p>⑦ <code>fs.mkdir(path[, mode], callback)</code><br>
在指定路径里创建一个文件夹</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
<span class="hljs-comment">// 在当前目录创建一个叫test的文件夹
fs.mkdir(<span class="hljs-string">'./test', err=>{
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(<span class="hljs-string">'文件夹创建成功');
})
</span></span></span></span></span></span></span></span></span></code></pre>
<p>⑧ <code>fs.rmdir(path, callback)</code><br>
删除指定路径下的文件夹</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.rmdir(<span class="hljs-string">'./test', err=>{
<span class="hljs-keyword">if (err) <span class="hljs-keyword">throw err;
<span class="hljs-built_in">console.log(<span class="hljs-string">'文件夹删除成功');
})
</span></span></span></span></span></span></span></span></code></pre>
<p>⑨ <code>fs.watch(filename[, options][, listener])</code><br>
和gulp里的watch很像,用来监视 filename的变化,filename 可以是<strong>一个文件或一个目录</strong>。</p>
<p>监听器回调有两个参数 (eventType, filename)。 eventType 可以是 'rename' 或 'change',filename 是触发事件的文件的名称。</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
fs.watch(<span class="hljs-string">'./', {
<span class="hljs-attr">recursive: <span class="hljs-literal">true <span class="hljs-comment">// 指明是否全部子目录应该被监视
}, (eventType, filename) =>{
<span class="hljs-built_in">console.log(eventType, filename);
})
</span></span></span></span></span></span></span></span></code></pre>
<p>注意,在大多数平台,当一个文件出现或消失在一个目录里时,'rename' 会被触发。</p>
<p>⑩ <code>fs.createReadStream(path[, options])</code><br>
返回一个新建的 ReadStream 对象</p>
<pre class="hljs javascript"><code class="javascript"><span class="hljs-keyword">const fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs');
<span class="hljs-keyword">const rs = fs.createReadStream(<span class="hljs-string">'./test.txt');
rs.pipe(process.stdout);<span class="hljs-comment">// 在终端输出test.txt内容</span></span></span></span></span></span></code></pre>
</div>
<p><br><br>作者:JokerPeng<br>链接:https://www.jianshu.com/p/22f62a08559f<br>来源:简书<br>简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。</p><br><br>
来源:https://www.cnblogs.com/telwanggs/p/10953174.html
頁:
[1]