Node.js 研究

4,489 阅读6分钟

浏览器中的js VS NodeJs中的js

)

浏览器中的js,就是ECMAScript语法+Web API。

NodeJs中的js,就是ECMAScript语法+Node API。

上图可以看到,语法都是相同的语法(ECMAScript),只不过所在的环境不同,提供的API不同,能干的事就不一样了。图没有列出所有的API,但可以看出,在NodeJS环境中提供的http(http服务相关)。就可以让NodeJs写出服务端程序了。

前端开发 VS 后端开发

前端开发思维 VS 后端开发思维

正如上面所说的,编程语言对于我们学习NodeJs不是障碍,就是ES语法。

首要转换我们的思维,前端是请求数据,然后处理请求结果。后端是接受请求,然后响应请求返回数据。

前后端注重的点,是不一样的,前端注重呈现和交互。后端注重安全和稳定。

前端技术栈 VS 后端技术栈

学习NodeJs是一项大工程,是要学习一整套技术,掌握后端的技术栈,才能真正在工作中使用。

我画一个大概的前后端技术栈对比图:

后端有些技术,是前端用不到的,比如数据库sql。也有些技术,是前后端公共的,比如cookie这种,后端还会注意set-cookie、和session相关的知识点。

相信通过上图,我们能了解NodeJs是什么级别的技术了,不是单指某项技术,而是指Js进行后端开发。

NodeJs知识梳理

启动服务

从总体上观察NodeJs后,再看看细节,第一步就是启动服务:

var http = require("http");

http.createServer(function(request, response) {
  // 处理一切
  // request接收请求
  // response响应请求
}).listen(8888);

NodeJs最主要的也就是这段代码了,服务端就是在接收/响应请求。NodeJs用了一个回调方法,我就可以在其中处理一切了。

路由

要处理不同的请求就写switch就行了。

http.createServer(function(request, response) {
  // 从request中获取请求url和method:get/post
  switch(url){
    case '/api/blog/list':
        // 返回博客列表相关代码
        break;
    case '/api/blog/new':
        // 新建博客相关代码
        break;
    ...
    case '/api/user/list':
        // 返回用户列表相关代码
        break;
    case '/api/user/new':
        // 新建用户相关代码
        break;
    ...
  }
}).listen(8888);

一个项目里,要在一个方法里写所有处理请求的代码,不合理,要拆分啊。就有了路由。

我们将不同的请求处理,放到不同的文件里,以blog/user这样的业务逻辑为分割:

// app.js
http.createServer(function(req, res) {
 handleBlogRouter(req, res)
 handleUserRouter(req, res)
}).listen(8888);
// router/blog.js
export default handleBlogRouter(req, res){
    ...
    switch(url){
    case '/api/blog/list':
        // 返回博客列表相关代码
        break;
    case '/api/blog/new':
        // 新建博客相关代码
        break;
    ...
  }
}
// router/user.js
export default handleBlogRouter(req, res){
    ...
    switch(url){
    case '/api/user/list':
        // 返回用户列表相关代码
        break;
    case '/api/user/new':
        // 新建用户相关代码
        break;
    ...
  }
}

后端的路由,和前端的路由,概念上还是有区别的,前端指页面跳转,一个页面一个路由。后端一个接口地址,指一个路由。

controler

我们继续拆分,让router也单一职责,将业务逻辑也抽离出来:

// router/blog.js
const {
    getBlogList,
    newBlog,
    ...
} = require('../controler/blog')

export default handleBlogRouter(req, res){
    ...
    switch(url){
    case '/api/blog/list':
        const result = getBlogList(id);
        res.json(result);
        break;
    case '/api/blog/new':
        const result = newBlog(body);
        res.json(result);
        break;
    ...
  }
}

这里将生成json、或者生成html等返回数据放在router里,但是业务逻辑,放在controler里。

项目结构

下面基本列一下项目结构,在我们不使用任何框架的情况下,也需要拆分代码。

└─bin #启动HTTP服务
    │   www.js      
├─logs #日志文件
└─src  #项目源码
    |   controler #放controler,业务逻辑
    |   model  #放model,数据模型,数据库操作
    |   router #路由相关
    |   utils #工具类文件
    |   db #数据库相关 mysql,redis等基本服务封装
    |   config #项目相关配置
├─app.js 主文件,启动文件

展示项目结构源码地址

我按这个基本的项目结构,写了个小项目,已上传到码云。点击这里查看

在项目中,还可以看到我对请求的主要处理,增强请求对象,包含获取 path 解析、 query解析、cookie设置、session封装、post请求封装。 设置响应对象,如设置返回格式为 JSON。

数据库

首先要选择一个数据库,我选择的是mysql。熟悉数据库工具,使用sql语句。

  1. 安装数据库,安装数据库可视化客户端
  2. nodejs连接数据库,将代码写到db文件夹中,接着在model文件夹中写sql语句,接着controler里在调用model中封装的方法。

cookie、session、redis

这三个知识点是有关联的。都是有关状态存储的。

http是无状态的,要想记录状态,就需要用cookie。服务端要记录更多安全的信息,就需要session。更好的利用服务端内存,增加稳定性,就需要redis内存数据库。

最典型的应用就是登录状态的记录。利用cookie记录一个key,利用session存储用户的敏感信息,也可将session存入redis中。

文件操作

服务端需要文件操作,当遇到大文件的时候,还需使用Stream流操作。

最典型的应用的地方,就是日志操作。

安全

服务端必不可少的一块内容就是安全方面的内容,放置xss攻击,sql注入攻击等。

express

理解了服务端开发的方方面面后,就可以上手一个框架了express目前应用的挺广的。

var express = require('express');
var app = express();

app.get('/', function (req, res) {
    res.send('Hello World!');
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!');
});

可以使用express-generator这样的脚手架,生成的项目,路由日志等模块,都集成好了。

npm install -g express-generator

中间件的使用

框架的核心机制就是插件机制。一个请求过来的时候,一个插件处理一下,交给下一个插件,处理完再交给下一个,逐个处理,最后由负责业务的插件返回响应结果。

这样就将职责拆分开来。让每个插件指处理单一的任务。并且是递进的,如上一个插件封装的操作cookie的相关方法,那下一个插件就可以在request对象中拿到对应的方法,处理业务。

koa2

了解过express后,再看Koa也容易上手了。区别于exress,一个是增加了异步,一个是插件机制变成了洋葱模型。

app.use(async (ctx, next) => {
    await next();
    var data = await doReadFile();
    ctx.response.type = 'text/plain';
    ctx.response.body = data;
});

插件的核心机制还是没有变的,也做到了对于一个请求的处理各个职责上的拆分。

koa2也有相应的脚手架

npm install -g koa-generator

nginx反向代理

由于我们的服务器上,即部署了前端也部署了后端,就需要一个反向代理来分配,那些是请求前端资源,哪些是请求后端资源了。

结束语

我只是node的入门阶段,这篇也只是对NodeJs开发的整体做一个大概的介绍。想学好nodeJs,还需多多实战,掌握后端开发的一些概念和技术。在实践中理解它的工作机制及原理。