Node.jsの基本:パートIII

第一章:概念に基づいて、サーバ

作曲1.1サイト

クライアント側とサーバー側:Webアプリケーションは、次の2つの部分に分けることができます。

  • クライアント:ブラウザで実行の一部、プログラムを見ると対話するためのユーザーインターフェースです。HTML、CSS、JavaScriptの建物を使用しました。
  • サーバー:データを格納し、アプリケーションロジックを処理するための責任のサーバでの動作の一部。

1.2ノードのサーバー

サイトでは、サービスへのアクセスを提供することができます要求に応答することができ、クライアントの要求を受け取ることができるサイトのサーバマシン、です。

1.3-IPアドレス

ユニークなインターネットデバイスを識別します。

IPは、インターネットプロトコルアドレスに代わって、インターネットプロトコルアドレスの略です。

1.4ドメイン

IPを覚えておくことが困難に対処するので、ドメイン名のコンセプトので、ドメイン名は、通常はインターネットURLを使用と呼ばれています。

http://www.baidu.com => http://39.156.66.14/

アドレスバーにURLの入力が、しかし、最終的には指定されたサイトサーバーにアクセスするために、IPドメイン名に変換されます。

1.5ポート

外の世界との通信は、サーバコンピュータに提供される各種サービスを区別するために使用されるコンピュータのポートACアウトレット、です。

1.6-URL

また、URL(ユニフォームリソースロケータ)として知られているユニフォームリソースロケータは、我々は通常URLであるウェブページのアドレスを参照してください、インターネットを識別し、位置を設定するために設計されたオンラインリソースに対処する方法です。

URLの構成は次のとおりです。传输协议://服务器IP或域名:端口/资源所在位置标识

https://www.baidu.com/index.html

1.7開発プロセス、クライアントとサーバ側

在开发阶段,客户端和服务器端使用同一台电脑,即开发人员电脑。

本机域名:localhost

本地IP :127.0.0.1

第二章:创建web服务器

// 1. 导入http模块
const http = require("http");
// 2. 创建web服务器对象
const app = http.createServer();
// 3. 给服务器注册request事件,监听用户请求,并作出响应
app.on("request", (req, res) => { 
  // 响应客户端
  res.end("Hello!")
});
// 4. 监听端口4000
app.listen(4000);

在本地浏览器总:输入地址→localhost:4000

第三章:HTTP协议

3.1-概念

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答的标准。

3.2-报文

在HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式。

3.3-请求报文

请求方式

  • get
  • post

请求地址

const http = require("http");
const app = http.createServer();
app.on("request", (req, res) => { 
  // 获取请求报文
  console.log(req.headers);
  // 获取请求的路径
  console.log(req.url);
  // 获取请求的方式
  console.log(req.method);
});
app.listen(4000);

3.4-响应报文

HTTP状态码

200 请求成功

404 请求的资源没有被找到

500 服务器端错误

400 客户端请求有语法错误

内容类型

text/html

text/css

application/javascript

image/jpeg

application/json

代码演示

const http = require("http");
const app = http.createServer();
app.on("request", (req, res) => { 
  // 设置响应报文(状态码和响应的内容类型与编码)
  res.writeHead(200, {
    "Content-Type":"text/html;charset=utf-8"
  })
  res.end("<h1>你好!</h1>");
});
app.listen(4000);

第四章:HTTP请求与响应处理

4.1-请求参数

​ 客户端向服务器端发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如查询操作、登录操作等。

4.2-GET请求参数

参数被放置在浏览器地址栏中,例如:http://localhost:3000/?id=1&type=2

参数获取需要借助系统模块url,url模块用来处理url地址

const http = require("http");
// 【导入url模块】
const url = require("url");
const app = http.createServer();
app.on("request", (req, res) => { 
  // 【将req.url转换为对象,并解构出 [请求路径] 和 [对象格式的请求参数]】
  let {query,pathname} = url.parse(req.url, true);
  // 请求路径
  console.log(pathname);
  // 请求参数对象
  console.log(query);
});
app.listen(3000);

4.3-POST请求参数

参数被放置在请求体中进行传输

获取POST参数需要使用data事件end事件

使用querystring系统模块将参数转换为对象格式

表单:

  <form action="http://localhost:4000" method="POST">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="pwd">
    <input type="submit">

  </form>

node服务

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

});
app.listen(4000);

4.4-路由

http://localhost:3000/index

http://localhost:3000/login

路由是指客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。

const http = require("http");
const url = require("url");
const app = http.createServer();
app.on("request", (req, res) => { 
  // 获取请求的路径
  let { pathname } = url.parse(req.url, true);
  // 设置响应头
  res.writeHead(200, { "content-Type": "text/html;charset=utf-8" });
  // 处理路由
  if (pathname == "/index.html" || pathname == "/") {
    res.end("<h1>首页</h1>");
  } else if (pathname == "/list.html") {
    res.end("<h1>列表页面</h1>");
  } else {
    res.writeHead(404, { "content-Type": "text/html;charset=utf-8" });
    res.end("<h1>页面不存在</h1>");
  }
  

});
app.listen(4000);

4.5-静态资源

服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,例如CSS、JavaScript、image文件。

https://m.360buyimg.com/babel/jfs/t1/36002/35/9106/3311/5cd4f1bdE06ff07ed/9570fdd46ecd3a76.png

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

});
app.listen(4000);

4.6-动态资源

相同的请求地址不同的响应资源,这种资源就是动态资源。

https://www.baidu.com/s?wd=美女

https://www.baidu.com/s?wd=帅哥

4.7-客户端请求途径

  • GET方式
    • 浏览器地址栏
    • link标签的href属性
    • script标签的src属性
    • img标签的src属性
    • Form表单提交
  • POST方式
    • Form表单提交

第五章:Node异步编程

5.1-同步API, 异步API

同步API:只有当前API执行完成后,才能继续执行下一个API

console.log('before'); 
console.log('after');

异步API:当前API的执行不会阻塞后续代码的执行

console.log('before');
setTimeout(
   () => { console.log('last');
}, 2000);
console.log('after');

区别1:同步API, 异步API的区别(返回值):

// 【同步】
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

区别2:同步API, 异步API的区别(代码执行顺序)

  • 同步API从上到下依次执行,前面代码会阻塞后面代码的执行
  • 异步API不会等待API执行完成后再向下执行代码

5.2-回调函数

回调函数的基本定义和使用

// getData函数定义
 function getData (callback) {}
  // getData函数调用
 getData (() => {});

使用回调函数获取异步API执行结果

function getMsg (callback) {
    setTimeout(function () {
        callback ({ msg: 'Hello Node.js' })
    }, 2000);
}
getMsg (function (msg) { 
    console.log(msg);  // 结果:Hello Node.js
});

5.3-异步代码执行顺序分析

console.log('代码开始执行');
setTimeout(() => {
    console.log('2秒后执行的代码');
}, 2000); 
setTimeout(() => {
    console.log('"0秒"后执行的代码');
}, 0);
console.log('代码结束执行');

5.4-Node.js中的异步API

需求:依次读取A文件、B文件、C文件

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);
    })
  })
});

问题:回调嵌套太多,代码不易于维护

解决方案:Promise对象

5.5-Promise对象

基本使用

let p1 = new Promise((resolve, reject) => { 
    // resolve表示执行成功后的函数
    // reject表示异常时的函数
  fs.readFile("./public/1.txt", "utf-8", function (err, data) {
    if (err) {
      reject(err);
    } else {
      resolve(data);
    }
  });
});

p1
  // 执行成功后的操作
  .then((data) => { console.log(data) })
  // 发生异常时的操作
  .catch((err) => { console.log(err) });

完成需求

const fs = require("fs");
function p1() {
  return new Promise((resolve, reject) => {
    fs.readFile("./public/a.txt", "utf-8", (err, data) => { 
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}
function p2() {
  return new Promise((resolve, reject) => {
    fs.readFile("./public/b.txt", "utf-8", (err, data) => { 
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}
function p3() {
  return new Promise((resolve, reject) => {
    fs.readFile("./public/c.txt", "utf-8", (err, data) => { 
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

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

5.6-异步函数

异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了。

关键字:async

语法:async function fn () {}const fn = async () => {};

  1. 普通函数定义前加async关键字 普通函数变成异步函数
  2. 异步函数默认返回promise对象
  3. 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法
  4. 在异步函数内部使用throw关键字抛出程序异常
  5. 调用异步函数再链式调用then方法获取异步函数执行结果
  6. 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
let fn1 = async () => { 
  // throw "异常";
  return "success";
};

fn1()
  .then((data) => { console.log(data) })
  .catch((err)=>{console.log(err)})

关键字:await

  1. await关键字只能出现在异步函数中
  2. await promise await后面只能写promise对象 写其他类型的API是不不可以的
  3. await关键字可是暂停异步函数向下执行 直到promise返回结果

完成需求

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();

おすすめ

転載: www.cnblogs.com/lpl666/p/12345608.html