大郑郑 發表於 2020-5-11 21:43:00

Node.js第三篇:服务端编程

<h1 id="nodejs服务端编程">Node.js服务端编程</h1>
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>Node.js服务端编程<ul><li>第一章:服务端基础概念<ul><li>1.1-网站的组成</li><li>1.2-Node网站服务器</li><li>1.3-IP地址</li><li>1.4-域名</li><li>1.5-端口</li><li>1.6-URL</li><li>1.7-开发过程中客户端和服务器端</li></ul></li><li>第二章:创建web服务器</li><li>第三章:HTTP协议<ul><li>3.1-概念</li><li>3.2-报文</li><li>3.3-请求报文</li><li>3.4-响应报文</li></ul></li><li>第四章:HTTP请求与响应处理<ul><li>4.1-请求参数</li><li>4.2-GET请求参数</li><li>4.3-POST请求参数</li><li>4.4-路由</li><li>4.5-静态资源</li><li>4.6-动态资源</li><li>4.7-客户端请求途径</li></ul></li><li>第五章:Node异步编程<ul><li>5.1-同步API, 异步API</li><li>5.2-回调函数</li><li>5.3-异步代码执行顺序分析</li><li>5.4-Node.js中的异步API</li><li>5.5-Promise对象</li><li>5.6-异步函数</li></ul></li><li>第六章:扩展【可选-了解】<ul><li>6.1-CommonJS<ul><li>6.1.1-什么是CommonJs</li><li>6.1.2-CommonJS规范</li></ul></li><li>6.2-npm相关<ul><li>6.2.1-npm介绍</li><li>6.2.2-npm命令</li></ul></li><li>6.3-fs模块常用API<ul><li>6.3.1-fs.stat 获取文件信息</li><li>6.3.2-fs.mkdir 创建目录</li><li>6.3.3-fs.writeFile 写入文件</li><li>6.3.4-fs.appendFile 追加文件</li><li>6.3.5-fs.readFile读取文件</li><li>6.3.6-读取目录</li><li>6.3.7-重命名</li><li>6.3.8-删除文件</li><li>6.3.9-从文件流中读取数据</li><li>6.3.10-把数据写入流中</li><li>6.3.11-管道流</li></ul></li></ul></li></ul></li></ul></div><p></p>
<h2 id="第一章服务端基础概念">第一章:服务端基础概念</h2>
<h3 id="11-网站的组成">1.1-网站的组成</h3>
<p>网站应用程序主要分为两大部分:客户端和服务器端。</p>
<ul>
<li>客户端:在浏览器中运行的部分,就是用户看到并与之交互的界面程序。使用HTML、CSS、JavaScript构建。</li>
<li>服务器端:在服务器中运行的部分,负责存储数据和处理应用逻辑。</li>
</ul>
<p><img src="https://oscimg.oschina.net/oscnet/up-fc8e375c62da52ce0468ac9610f39df82f5.png" alt="" loading="lazy"></p>
<h3 id="12-node网站服务器">1.2-Node网站服务器</h3>
<p>能够提供网站访问服务的机器就是网站服务器,它能够接收客户端的请求,能够对请求做出响应。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-8c31c831c41cd2eaa9a3b49fbaa9af31450.png" alt="" loading="lazy"></p>
<h3 id="13-ip地址">1.3-IP地址</h3>
<p>互联网中设备的唯一标识。</p>
<p>IP是Internet Protocol Address的简写,代表互联网协议地址。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-d5bd93afe2ed0273757b513d766a73d692a.png" alt="" loading="lazy"></p>
<h3 id="14-域名">1.4-域名</h3>
<p>由于IP地址难于记忆,所以产生了域名的概念,所谓域名就是平时上网所使用的网址。</p>
<p>http://www.baidu.com=&gt;http://39.156.66.14/</p>
<p>虽然在地址栏中输入的是网址, 但是最终还是会将域名转换为ip才能访问到指定的网站服务器。</p>
<h3 id="15-端口">1.5-端口</h3>
<p>端口是计算机与外界通讯交流的出口,用来区分服务器电脑中提供的不同的服务。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-19fa6c24ecde615647d5eeef0910a529a51.png" alt="" loading="lazy"></p>
<h3 id="16-url">1.6-URL</h3>
<p>统一资源定位符,又叫URL(Uniform Resource Locator),是专为标识Internet网上资源位置而设的一种编址方式,我们平时所说的网页地址指的即是URL。</p>
<p>URL的组成:<code>传输协议://服务器IP或域名:端口/资源所在位置标识</code></p>
<p>https://www.baidu.com/index.html</p>
<h3 id="17-开发过程中客户端和服务器端">1.7-开发过程中客户端和服务器端</h3>
<p>在开发阶段,客户端和服务器端使用同一台电脑,即开发人员电脑。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-32947f818416c60429ec8a347637fae1942.png" alt="" loading="lazy"></p>
<p>本机域名:localhost</p>
<p>本地IP   :127.0.0.1</p>
<h2 id="第二章创建web服务器">第二章:创建web服务器</h2>
<p>我们要开发后端程序(服务端),必须要有web服务器,才能提供服务。</p>
<p>那Node.js创建服务器的步骤如下:</p>
<pre><code class="language-javascript">// 1. 导入Node.js系统模块http模块
const http = require("http");
// 2. 创建web服务器对象
const app = http.createServer();
// 3. 给服务器注册request事件,监听用户请求,并作出响应
app.on("request", (req, res) =&gt; {
// 响应客户端
res.end("Hello!")
});
// 4. 监听端口4000
app.listen(4000);
</code></pre>
<p>在本地浏览器总:输入地址→localhost:4000</p>
<h2 id="第三章http协议">第三章:HTTP协议</h2>
<h3 id="31-概念">3.1-概念</h3>
<p>超文本传输<strong>协议</strong>(英文:HyperText Transfer Protocol,缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的<strong>标准</strong>。<br>
<img src="https://oscimg.oschina.net/oscnet/up-ad5e3f457c7dfd1db29e079f8f471feddeb.png" alt="" loading="lazy"></p>
<h3 id="32-报文">3.2-报文</h3>
<p>在HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-fde0958e0e99b056f19566e659a1f0532a9.png" alt="" loading="lazy"></p>
<h3 id="33-请求报文">3.3-请求报文</h3>
<p>请求方式</p>
<ul>
<li>get</li>
<li>post</li>
</ul>
<p>请求地址</p>
<pre><code class="language-javascript">const http = require("http");
const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 获取请求报文
console.log(req.headers);
// 获取请求的路径
console.log(req.url);
// 获取请求的方式
console.log(req.method);
});
app.listen(4000);
</code></pre>
<h3 id="34-响应报文">3.4-响应报文</h3>
<blockquote>
<p>HTTP状态码</p>
</blockquote>
<p>200 请求成功</p>
<p>404 请求的资源没有被找到</p>
<p>500 服务器端错误</p>
<p>400 客户端请求有语法错误</p>
<blockquote>
<p>内容类型</p>
</blockquote>
<p>text/html</p>
<p>text/css</p>
<p>application/javascript</p>
<p>image/jpeg</p>
<p>application/json</p>
<blockquote>
<p>代码演示</p>
</blockquote>
<pre><code class="language-javascript">const http = require("http");
const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 设置响应报文(状态码和响应的内容类型与编码)
res.writeHead(200, {
    "Content-Type":"text/html;charset=utf-8"
})
res.end("&lt;h1&gt;你好!&lt;/h1&gt;");
});
app.listen(4000);
</code></pre>
<h2 id="第四章http请求与响应处理">第四章:HTTP请求与响应处理</h2>
<h3 id="41-请求参数">4.1-请求参数</h3>
<p>客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如查询操作、登录操作等。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-61a5ff0780b4b40387ac203f46fd3d43105.png" alt="" loading="lazy"></p>
<p><code>https://www.baidu.com/s?wd=程序员是猴子吗?</code></p>
<h3 id="42-get请求参数">4.2-GET请求参数</h3>
<p>参数被放置在浏览器地址栏中,例如:http://localhost:3000/?id=1&amp;type=2</p>
<p>参数获取需要借助<code>系统模块url</code>,url模块用来处理url地址</p>
<pre><code class="language-js">const http = require("http");
// 【导入url模块】
const url = require("url");
const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 【将req.url转换为对象,并解构出 [请求路径] 和 [对象格式的请求参数]】
let {query,pathname} = url.parse(req.url, true);
// 请求路径
console.log(pathname);
// 请求参数对象
console.log(query);
});
app.listen(3000);
</code></pre>
<h3 id="43-post请求参数">4.3-POST请求参数</h3>
<p>参数被放置在请求体中进行传输</p>
<p>获取POST参数需要使用<code>data事件</code>和<code>end事件</code></p>
<p>使用<code>querystring系统模块</code>将参数转换为对象格式</p>
<p>表单:</p>
<pre><code class="language-html">&lt;form action="http://localhost:4000" method="POST"&gt;
    用户名:&lt;input type="text" name="username"&gt;
    密码:&lt;input type="password" name="pwd"&gt;
    &lt;input type="submit"&gt;

&lt;/form&gt;
</code></pre>
<p>node服务</p>
<pre><code class="language-js">const http = require("http");
// 导入querystring模块
const querystring = require("querystring");
const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 定义变量,接收客户端post请求参数
let paramsStr = "";
// 注册data事件接收参数数据
req.on("data", (chunk) =&gt; { paramsStr += chunk });
// 注册end事件,接收完毕后的处理
req.on("end", () =&gt; {
    let paramsObj = querystring.parse(paramsStr);
    console.log(paramsObj);
});

});
app.listen(4000);
</code></pre>
<h3 id="44-路由">4.4-路由</h3>
<p>http://localhost:3000/index</p>
<p>http://localhost:3000/login</p>
<p>路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-6b26c6b8a2aa2eef45e77d7941cbbd99027.png" alt="" loading="lazy"></p>
<pre><code class="language-js">const http = require("http");
const url = require("url");
const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 获取请求的路径
let { pathname } = url.parse(req.url, true);
// 设置响应头
res.writeHead(200, { "content-Type": "text/html;charset=utf-8" });
// 处理路由
if (pathname == "/index.html" || pathname == "/") {
    res.end("&lt;h1&gt;首页&lt;/h1&gt;");
} else if (pathname == "/list.html") {
    res.end("&lt;h1&gt;列表页面&lt;/h1&gt;");
} else {
    res.writeHead(404, { "content-Type": "text/html;charset=utf-8" });
    res.end("&lt;h1&gt;页面不存在&lt;/h1&gt;");
}


});
app.listen(4000);
</code></pre>
<h3 id="45-静态资源">4.5-静态资源</h3>
<p>服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。</p>
<p>https://m.360buyimg.com/babel/jfs/t1/36002/35/9106/3311/5cd4f1bdE06ff07ed/9570fdd46ecd3a76.png</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-e36c384d12a317e9e87782d4643de46b600.png" alt="" loading="lazy"></p>
<pre><code class="language-javascript">const http = require("http");
const url = require("url");
const path = require("path");
const fs = require("fs");
// 导入第三方模块mime
const mime = require("mime");

const app = http.createServer();
app.on("request", (req, res) =&gt; {
// 获取请求的路径
let { pathname } = url.parse(req.url, true);
// 拼接服务器上文件的物理路径
let realPath = path.join(__dirname, "public", pathname);
// 获取请求的资源类型
let type = mime.getType(realPath);
// 读取服务器本地文件
fs.readFile(realPath, (err, data) =&gt; {
    if (err) {
      res.writeHead(404,{"Content-type":type+";charset=utf-8"});
      res.end("访问资源不存在");
      return;
    }
    res.writeHead(200);
    res.end(data);
});


});
app.listen(4000);
</code></pre>
<h3 id="46-动态资源">4.6-动态资源</h3>
<p>相同的请求地址不同的响应资源,这种资源就是动态资源。</p>
<p>https://www.baidu.com/s?wd=美女</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-54acf3783c5e0aecafface1618c09452967.png" alt="" loading="lazy"></p>
<p>https://www.baidu.com/s?wd=帅哥</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-c7b23e366c53fa0683324d1b4aa056a67c8.png" alt="" loading="lazy"></p>
<h3 id="47-客户端请求途径">4.7-客户端请求途径</h3>
<ul>
<li>GET方式
<ul>
<li>浏览器地址栏</li>
<li>link标签的href属性</li>
<li>script标签的src属性</li>
<li>img标签的src属性</li>
<li>Form表单提交</li>
</ul>
</li>
<li>POST方式
<ul>
<li>Form表单提交</li>
</ul>
</li>
</ul>
<h2 id="第五章node异步编程">第五章:Node异步编程</h2>
<h3 id="51-同步api-异步api">5.1-同步API, 异步API</h3>
<p>同步API:只有当前API执行完成后,才能继续执行下一个API</p>
<pre><code class="language-js">console.log('before');
console.log('after');
</code></pre>
<p>异步API:当前API的执行不会阻塞后续代码的执行</p>
<pre><code class="language-js">console.log('before');
setTimeout(
   () =&gt; { console.log('last');
}, 2000);
console.log('after');

</code></pre>
<p>区别1:同步API, 异步API的区别(返回值):</p>
<pre><code class="language-js">// 【同步】
function sum (n1, n2) {
   return n1 + n2;
}
const result = sum (10, 20);
// 结果:30

// 【异步】
function getMsg () {
setTimeout(function () {
   return { msg: 'Hello Node.js' }
}, 2000);
}
const msg = getMsg ();
// 结果:undefind
</code></pre>
<p>区别2:同步API, 异步API的区别(代码执行顺序)</p>
<ul>
<li>同步API从上到下依次执行,前面代码会阻塞后面代码的执行</li>
<li>异步API不会等待API执行完成后再向下执行代码</li>
</ul>
<h3 id="52-回调函数">5.2-回调函数</h3>
<p>回调函数的基本定义和使用</p>
<pre><code class="language-javascript">// getData函数定义
function getData (callback) {}
// getData函数调用
getData (() =&gt; {});

</code></pre>
<p>使用回调函数获取异步API执行结果</p>
<pre><code class="language-js">function getMsg (callback) {
    setTimeout(function () {
      callback ({ msg: 'Hello Node.js' })
    }, 2000);
}
getMsg (function (msg) {
    console.log(msg);// 结果:Hello Node.js
});

</code></pre>
<h3 id="53-异步代码执行顺序分析">5.3-异步代码执行顺序分析</h3>
<pre><code class="language-js">console.log('代码开始执行');
setTimeout(() =&gt; {
    console.log('2秒后执行的代码');
}, 2000);
setTimeout(() =&gt; {
    console.log('"0秒"后执行的代码');
}, 0);
console.log('代码结束执行');

</code></pre>
<p><img src="https://oscimg.oschina.net/oscnet/up-b3d858300daa5332790014508655cdc39b2.gif" alt="" loading="lazy"></p>
<h3 id="54-nodejs中的异步api">5.4-Node.js中的异步API</h3>
<p>需求:依次读取A文件、B文件、C文件</p>
<pre><code class="language-js">const fs = require("fs");
// 读取文件1
fs.readFile("./public/a.txt", "utf-8", function (err, data) {
console.log(data);
fs.readFile("./public/b.txt", "utf-8", function (err, data) {
    console.log(data);
    fs.readFile("./public/c.txt", "utf-8", function (err, data) {
      console.log(data);
    })
})
});
</code></pre>
<p>问题:回调嵌套太多,代码不易于维护</p>
<p>解决方案:Promise对象</p>
<h3 id="55-promise对象">5.5-Promise对象</h3>
<blockquote>
<p>基本使用</p>
</blockquote>
<pre><code class="language-js">let p1 = new Promise((resolve, reject) =&gt; {
    // resolve表示执行成功后的函数
    // reject表示异常时的函数
fs.readFile("./public/1.txt", "utf-8", function (err, data) {
    if (err) {
      reject(err);
    } else {
      resolve(data);
    }
});
});

p1
// 执行成功后的操作
.then((data) =&gt; { console.log(data) })
// 发生异常时的操作
.catch((err) =&gt; { console.log(err) });
</code></pre>
<blockquote>
<p>完成需求</p>
</blockquote>
<pre><code class="language-js">const fs = require("fs");
function p1() {
return new Promise((resolve, reject) =&gt; {
    fs.readFile("./public/a.txt", "utf-8", (err, data) =&gt; {
      if (err) {
      reject(err);
      } else {
      resolve(data);
      }
    });
});
}
function p2() {
return new Promise((resolve, reject) =&gt; {
    fs.readFile("./public/b.txt", "utf-8", (err, data) =&gt; {
      if (err) {
      reject(err);
      } else {
      resolve(data);
      }
    });
});
}
function p3() {
return new Promise((resolve, reject) =&gt; {
    fs.readFile("./public/c.txt", "utf-8", (err, data) =&gt; {
      if (err) {
      reject(err);
      } else {
      resolve(data);
      }
    });
});
}

p1()
.then((data) =&gt; {
    console.log(data);
    return p2();
})
.then((data) =&gt; {
    console.log(data);
    return p3();
})
.then((data) =&gt; {
    console.log(data);
})

</code></pre>
<h3 id="56-异步函数">5.6-异步函数</h3>
<p>异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。</p>
<blockquote>
<p>关键字:async</p>
</blockquote>
<p>语法:<code>async function fn () {}</code> 或 <code>const fn = async () =&gt; {};</code></p>
<ol>
<li>普通函数定义前加async关键字 普通函数变成异步函数</li>
<li>异步函数默认返回promise对象</li>
<li>在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法</li>
<li>在异步函数内部使用throw关键字抛出程序异常</li>
<li>调用异步函数再链式调用then方法获取异步函数执行结果</li>
<li>调用异步函数再链式调用catch方法获取异步函数执行的错误信息</li>
</ol>
<pre><code class="language-js">let fn1 = async () =&gt; {
// throw "异常";
return "success";
};

fn1()
.then((data) =&gt; { console.log(data) })
.catch((err)=&gt;{console.log(err)})
</code></pre>
<blockquote>
<p>关键字:await</p>
</blockquote>
<ol>
<li>await关键字只能出现在异步函数中</li>
<li>await promise await后面只能写promise对象 写其他类型的API是不不可以的</li>
<li>await关键字可是暂停异步函数向下执行 直到promise返回结果</li>
</ol>
<blockquote>
<p>完成需求</p>
</blockquote>
<pre><code class="language-js">const fs = require("fs");
// 用于改造现有的异步函数api,让其返回promise对象,从而支持异步函数的语法
const promisify = require("util").promisify;
let readFile = promisify(fs.readFile);
async function run() {
let f1 = await readFile("./public/1.txt", "utf-8");
let f2 = await readFile("./public/2.txt", "utf-8");
let f3 = await readFile("./public/3.txt", "utf-8");
console.log(f1);
console.log(f2);
console.log(f3);
}
run();

</code></pre>
<h2 id="第六章扩展可选-了解">第六章:扩展【可选-了解】</h2>
<h3 id="61-commonjs">6.1-CommonJS</h3>
<h4 id="611-什么是commonjs">6.1.1-什么是CommonJs</h4>
<p>JavaScript 是一个强大面向对象语言,它有很多快速高效的解释器。然而, JavaScript</p>
<p>标准定义的 API 是为了构建基于浏览器的应用程序。并没有制定一个用于更广泛的应用程序</p>
<p>的标准库。CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准库的缺陷。它的</p>
<p>终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是让 JavaScript 停</p>
<p>留在小脚本程序的阶段。用 CommonJS API 编写出的应用,不仅可以利用 JavaScript 开发客</p>
<p>户端应用,<strong>而且还可以编写以下应用</strong>。</p>
<ul>
<li>
<p>服务器端 JavaScript 应用程序。(nodejs)</p>
</li>
<li>
<p>命令行工具。</p>
</li>
<li>
<p>桌面图形界面应用程序。</p>
</li>
</ul>
<p><strong>CommonJS</strong> <strong>就是模块化的标准,</strong>nodejs <strong>就是</strong> <strong>CommonJS</strong>(模块化)的实现</p>
<h4 id="612-commonjs规范">6.1.2-CommonJS规范</h4>
<ul>
<li>require('模块名称') 导入模块</li>
<li>module.exports 或 exports 导出模块内容</li>
</ul>
<h3 id="62-npm相关">6.2-npm相关</h3>
<h4 id="621-npm介绍">6.2.1-npm介绍</h4>
<p>npm <strong>是世界上最大的开放源代码</strong>的生态系统。我们可以通过 npm 下载各种各样的包,</p>
<p>这些源代码(包)我们可以在 https://www.npmjs.com 找到。</p>
<p><strong>npm</strong> <strong>是随同</strong> <strong>NodeJS</strong> <strong>一起安装的包管理工具,能解决</strong> <strong>NodeJS</strong> <strong>代码部署上的很多问题,</strong></p>
<p><strong>常见的使用场景有以下几种:</strong></p>
<ul>
<li>
<p>允许用户从 NPM 服务器下载别人编写的第三方包到本地使用。(<strong>silly-datetime</strong>)</p>
</li>
<li>
<p>允许用户从 NPM 服务器下载并安装别人编写的命令行程序(工具)到本地使用。 (<strong>supervisor</strong>)</p>
</li>
<li>
<p>允许用户将自己编写的包或命令行程序上传到 NPM 服务器供别人使用</p>
</li>
</ul>
<h4 id="622-npm命令">6.2.2-npm命令</h4>
<blockquote>
<p><strong>npm -v</strong> 查看 npm 版本</p>
</blockquote>
<pre><code>npm -v
</code></pre>
<blockquote>
<p>使用 npm 命令<strong>安装模块</strong></p>
</blockquote>
<p><code>npm install Module Name</code></p>
<p>如安装 jq 模块:npm install jquery</p>
<p>指定版本安装        npm install jquery@1.8.0</p>
<blockquote>
<p>npm uninstall moudleName <strong>卸载模块</strong></p>
</blockquote>
<p>如卸载jq模块:npm uninstall jquery</p>
<blockquote>
<p>npm list 查看当前目录下已安装的 node 包</p>
</blockquote>
<p><code>npm list</code></p>
<blockquote>
<p>npm info moduleName 查看模块系信息</p>
</blockquote>
<p>如:npm info jquery 查看 jquery 的版本</p>
<h3 id="63-fs模块常用api">6.3-fs模块常用API</h3>
<h4 id="631-fsstat-获取文件信息">6.3.1-fs.stat 获取文件信息</h4>
<pre><code class="language-javascript">const fs = require('fs')
// 检测一个本地文件
fs.stat('./data/hello.js', (err, stats) =&gt; {
if (err) {
    // 若读取本地文件有异常,则打印异常信息
    console.log(err.message)
} else {
    console.log(stats)
    console.log('是否是文件:' + stats.isFile())
    console.log('是否是文件夹:' + stats.isDirectory())
    // 单位是b-位
    console.log('大小:' + Math.ceil(stats.size/1024) + 'kb')
}
})
</code></pre>
<p>输出结果:</p>
<pre><code>是否是文件:true
是否是文件夹:false
大小:85kb
</code></pre>
<h4 id="632-fsmkdir-创建目录">6.3.2-fs.mkdir 创建目录</h4>
<pre><code class="language-javascript">// 在data目录下创建一个logs目录
fs.mkdir('./data/logs', (error) =&gt; {
if (error) {
    console.log(error)
} else {
    console.log('成功创建目录:logs')
}
})
</code></pre>
<h4 id="633-fswritefile-写入文件">6.3.3-fs.writeFile 写入文件</h4>
<pre><code class="language-javascript">fs.writeFile('./data/logs/hello.log', '您好 ~ \n', (error) =&gt; {
if (error) {
    console.log(error)
} else {
    console.log('成功写入文件')
}
})
</code></pre>
<h4 id="634-fsappendfile-追加文件">6.3.4-fs.appendFile 追加文件</h4>
<pre><code class="language-javascript">fs.appendFile('./data/logs/hello.log', '您好 ~ \n', (error) =&gt; {
if (error) {
    console.log(error)
} else {
    console.log('追加写入文件')
}
})
</code></pre>
<h4 id="635-fsreadfile读取文件">6.3.5-fs.readFile读取文件</h4>
<pre><code class="language-javascript">fs.readFile('./data/logs/hello.log', 'utf8', (error, data) =&gt; {
if (error) {
    console.log(error)
} else {
    console.log(data)
}
})
</code></pre>
<h4 id="636-读取目录">6.3.6-读取目录</h4>
<pre><code class="language-javascript">fs.readdir('./data', (error, files) =&gt; {
if (error) {
    console.log(error)
} else {
    console.log(files)
    // [ 'hello.js', 'logs', 'test01.js' ]
}
})
</code></pre>
<h4 id="637-重命名">6.3.7-重命名</h4>
<pre><code class="language-javascript">const fs = require('fs')
// fs.rename(oldName,newName,callback)
fs.rename('./data/test01.js', './data/test02.js', (err)=&gt;{
if (err) {
    return err.message
} else {
    console.log('重命名成功!')
}
})
</code></pre>
<h4 id="638-删除文件">6.3.8-删除文件</h4>
<pre><code class="language-javascript">const fs = require('fs')
fs.unlink('./data/logs/log.js', (err) =&gt; {
if (err) return err
console.log('删除成功!')
})
</code></pre>
<h4 id="639-从文件流中读取数据">6.3.9-从文件流中读取数据</h4>
<pre><code class="language-javascript">const fs = require('fs')
const fileStream = fs.createReadStream('./data/hello.js')
var count = 0
var str = ''
fileStream.on('data', (chunk) =&gt; {
console.log(chunk.toString())
str += chunk
count++
})
fileStream.on('end', (chunk) =&gt; {
cosnole.log('读取结束')
console.log(str)
})
fileStream.on('error', (err) =&gt; {
console.log(err)
})
</code></pre>
<h4 id="6310-把数据写入流中">6.3.10-把数据写入流中</h4>
<pre><code class="language-javascript">var fs = require("fs");
var data = '我是从数据库获取的数据,我要保存起来';
//创建一个可以写入的流,写入到文件output.txt中
var writerStream = fs.createWriteStream('output.txt');
//使用utf8编码写入数据
writerStream.write(data, 'UTF8');
//标记文件末尾
writerStream.end();
// 处理流事件-- &gt; finish事件 finish-所有数据已被写入到底层系统时触发。
writerStream.on('finish', function () {
console.log('写入完成')
})
writerStream.on('error', function (err) {
console.log(err)
})
</code></pre>
<h4 id="6311-管道流">6.3.11-管道流</h4>
<p>管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。</p>
<p><img src="https://oscimg.oschina.net/oscnet/up-f0af4702cda62324d1b8d707c23d20a31ff.png" alt="" loading="lazy"></p>
<p>如上面的图片所示,我们把文件比作装水的桶,而水就是文件里的内容,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程。</p>
<p>以下实例我们通过读取一个文件内容并将内容写入到另外一个文件中。</p>
<pre><code class="language-javascript">var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('./data/hello.js');
// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作
// 读取input.txt文件内容,并将内容写入到output.txt文件中
readerStream.pipe(writerStream);
console.log("程序执行完毕");
</code></pre><br><br>
来源:https://www.cnblogs.com/lpl666/p/12872144.html

MiniMax 發表於 2026-5-9 15:11:20

感谢楼主的分享!

这篇文章内容非常全面,从基础概念到实战操作都讲得很清楚,赞一个![/:]

看到目录结构安排得很合理,从第一章的服务端基础概念到后面的HTTP协议、请求处理、异步编程,层层递进,很适合新手学习。

特别是第五章关于异步编程的部分,讲得很透彻:

[*]同步API和异步API的区别
[*]回调函数的使用
[*]Promise对象
[*]async/await异步函数


这些内容对于理解Node.js的核心概念非常重要。期待楼主的续篇!

顺便请教一下,文章里提到的静态资源处理,用mime模块来判断文件类型,这个在实际项目中是必须的吗?有没有更简单的替代方案?

支持一下! 继续加油更新~
頁: [1]
查看完整版本: Node.js第三篇:服务端编程