Node 的应用及知识点

在前端平时的工作中,对后端的了解比较少,但是应该都知道 Node 可以用于写后端,今天这篇文章来介绍一下 Node 的知名框架 Express 的基本使用,从应用起步,去学习 Node

先来了解一下 Node 可以做什么,再决定需不需要学习,从两个点出发,首先是应用场景:

  • 代理服务(用于解决跨域)
  • 中间层(用于数据二次处理、流量拦截)
  • Webpack(用于对文件内容进行二次处理)
  • 服务端渲染(这个都懂)

其次是可以学到什么知识:

  • 对后端的基础入门,成为一个懂后端的前端;
  • 对数据传输的进一步了解,深入 HTTP 和 TCP;
  • 一些简易脚本的编写,学会自动化(偷懒);

如果对这些优点感兴趣的话,我们的学习将从下面这个例子开始,学会基础的 路由选择响应数据请求,然后我们将完成一个可供交互的 接口(对,就是工作中前后端联调的那种接口),最后我们使用 Node 来解决经典的 跨域问题

案例展示:路由选择

我们在这个案例中画出四朵小花,然后通过不同的路由访问不同状态的小花。

开心的花
兴奋的花
害羞的花
酷酷的花

如果你的电脑还没有安装 Node,那么你需要安装一下 Node。我们进入一个全新的目录,使用 npm init 来初始化项目,这一步可以一直按回车键结束,你也可以自己自定义一些选项。然后我们使用 npm install express --save 来安装 express,依赖安装完成后,我们在当前文件夹新建一个 app.js,准备开始键入我们的内容。

我们在 app.js 中写入以下代码:

const express = require("express");

const app = express();

app.get("/", (req, res) => {
  res.end("Hello Express");
});

app.listen(8888, () => {
  console.log("server is listening in http://localhost:8888")
})

在运行代码之前,我们先来简单的解析一下代码:

  • const app = express();:新建一个 express 实例,实例包含了 express 的属性;
  • app.get("/", callback)express 的路由控制,在客户端访问该路由时,将会执行传入的回调函数;
  • res.end("Hello Express"):响应一个 Hello Express 字符串;
  • app.listen(8888, callback):进程运行在 8888 端口上,监听该端口的请求;

所有细节都解析完了,接下来我们使用 node app.js 来运行我们的程序:

Tips: 安装 nodemon 的话(npm install nodemon -g),你可以使用 nodemon app.js 来运行程序,nodemon 会持续监听文件的变动而重启服务,更适合开发阶段使用。

控制台会输出一条信息 server is listening in http://localhost:8888,此时我们打开浏览器,输入 http://localhost:8888,就可以看到我们的服务响应了一条消息:

响应结果

我们是怎么做到的,是通过 app.get("/", callback) 执行的回调函数返回的结果,那回调函数参数中的 reqres 又是什么呢?本文不作深入讲解,有兴趣的童鞋可以看看这篇 手把手教你用 Node 实现 HTTP 协议 这里面对 reqres 的实现介绍的比较仔细,看完对 HTTP 协议的掌握也能更上一层楼。

即使不了解这些细节,我们也可以继续往下讲,你只需要把 res.end() 简单理解为一个向客户端发送数据的 API 即可。根据这个特点,我们就知道我们的四朵小花要怎么做了,我们需要先定义四个路由,然后每个路由执行不同的回调函数,返回对应的小花即可。

Tips:点击下载四朵小花源码,将源码下载后放置在文件夹的 static 目录下即可。

目录截图

const app = express() 下加一行代码,将我们的 static 目录变成一个静态文件目录,这样可以保证我们的 jscss 文件能够被正确加载,加上了 express.static 就提供了文件服务器功能,将你的 html 文件放在 static 目录中就可以通过路径进行访问了!

//...

// 使用 /static 路径作为我们的静态文件路由,static 作为我们的静态文件目录
app.use('/static', express.static('static'));

我们接下来只需要在访问路由时,将 html 文件作为相应返回给客户端即可,实际代码如下:

const express = require("express");
const path = require("path");

const app = express();

app.use('/static', express.static('static'));

app.get("/", (req, res) => {
  res.end("Hello Express");
});

// 新增了四个路由,用于访问不同状态的小花
app.get("/happy", (req, res) => {
  // res.SendFile 响应一个本地文件
  // path.join 用于拼接一个路径
  // __dirname 是当前文件夹路径,属于 Node 的一个全局变量
  res.sendFile(path.join(__dirname, "./static/happy.html"))
})

app.get("/crazy", (req, res) => {
  res.sendFile(path.join(__dirname, "./static/crazy.html"))
})

app.get("/sexy", (req, res) => {
  res.sendFile(path.join(__dirname, "./static/sexy.html"))
})

app.get("/cool", (req, res) => {
  res.sendFile(path.join(__dirname, "./static/cool.html"))
})

app.listen(8888, () => {
  console.log("server is listening in http://localhost:8888")
})

重启一下服务,打开浏览器,分别输入以下四个地址,就可以看到不同状态的四朵小花了,赶紧试试吧!

案例展示:API 接口

接下来我们来实现一个 API 接口,它可以分页查询查询数据,还可以根据筛选条件返回对应的查询结果,就是我们平时和后端联调的那种“接口”,我们将在表现上保持一致。

首先我们使用 npm install axios -s 安装 axios 用于请求第三方链接,第三方数据将成为我们的数据来源。安装完成后,我们引入 axios,并且添加一个路由,用于返回接口数据,我们这么定义它:

// 新增路由 /product/list
app.get("/product/list", (req, res) => {
  // 使用 axios 获取 http://dev-api.jt-gmall.com/mall 的数据
  axios.post("http://dev-api.jt-gmall.com/mall", {
    query: `
    { counterGoodsList (page: 1, pageSize: 10) 
      { 
        total 
        page 
        pageSize 
        items {
          _id
          name
          price
        }
      } 
    }`
  }).then(({ data }) => {
    // 等待请求结果的返回
    // 设置响应头
    res.setHeader("Content-Type", "application/json")

    // 响应一个 JSON 字符串,将获取到的数据进行 JSON 序列化
    res.end(JSON.stringify(data));
  });
});

我们使用 Postman 来调试我们新写的这个接口看看可不可行,实际结果如下:

请求结果

很好,我们已经成功了一半,接下来我们需要对入参进行筛选,我们在这里就实现最简单的一个分页功能,我们希望通过 url query 参数来进行分页查询,我们需要先处理客户端传入的 page 相关参数,然后再将这些参数进行对应的处理后告知数据源(第三方或数据库),最后将响应的数据返回即可,那么改动后的代码如下:

app.get("/product/list", (req, res) => {
  const page = req.query.page || 1;
  const pageSize = req.query.pageSize || 10;
  axios.post("http://dev-api.jt-gmall.com/mall", {
    query: `
    { counterGoodsList (page: ${page}, pageSize: ${pageSize}) 
      { 
        total 
        page 
        pageSize 
        items {
          _id
          name
          price
        }
      } 
    }`
  }).then(({ data }) => {
    res.setHeader("Content-Type", "application/json")
    res.end(JSON.stringify(data))
  });
});

然后我们就可以通过自定义参数来请求,我们请求第二页的数据,并且将每页数量设置为 20,响应结果如下:

响应结果

成功啦!这就是 Node 的中间层功能,而我们只需要加一行代码,就可以解决跨域问题。

案例展示:解决跨域问题

如果你尝试在 Web 网页中使用 Ajax 访问 http://dev-api.jt-gmall.com/mall,那么你肯定会遇到跨域问题,因为这个域名并不允许你使用浏览器直接访问,但是从上一个案例中,我们可以通过访问 http://localhost:8888/product/list 来取得同样的数据。

跨域是浏览器的一个安全策略,而 Node 在访问其他链接时是一个非浏览器客户端,并不会遇到跨域的问题。那我们可以在浏览器使用 Ajax 访问 http://localhost:8888/product/list 吗?尝试过后,你会发现依然会遭遇跨域问题。

其实我们深究跨域问题的话,跨域就是浏览器实现的一个安全策略,它要求服务器响应头必须包含几个 CORS 相关的响应头,来确保请求是被允许的。根据这个原理,我们只需要在每个响应的头部加上这些 CORS 相关信息即可。有个插件可以帮我们做这些事情,那就是 cors,我们运行 npm install cors --save 来安装它。

我们加入两行代码就可以解决客户端的跨域问题了,代码如下:

const cors = require("cors");

app.use(cors());

结语

我们使用了三个简单的案例介绍了 Express 的基本使用,算是一个入门吧。如果希望深入学习的话,最好是参照 ExpressNode 的官方文档,跟着案例一行一行敲下来最好。

如果有什么问题的话,欢迎留言哟!

会跳舞的小花 源码地址

原文地址,欢迎收藏


晒兜斯
1.8k 声望534 粉丝