由于最近项目上的原因,公司采用了node中间层,通过它来担当前端和真正意义上的后端之间的中转纽带。原因是我参与的这个项目是一个大型的云计算控制台,里面所涉及到的接口可谓是“鱼龙混杂”,有自己部门开发的接口,也有其他部门开发的接口,所以接口按照功能模块分为很多系列,不同的接口host也千差万别,如果不请node这个“大咖”介入,真的是乱了套了。
node这个东西能让js运行在服务端,对于前端来说浏览器的js引擎可以作为js的解释器,对于node来说,解释器是谷歌的v8引擎。你可以用node来写自己的服务器,这个服务器可以是代理服务器,也可以是提供数据的源服务器。目前来说源服务器一般还是采用比较稳定的java、python来搞得居多,node比较适合一些高并发的场景,还有就是在项目中充当中转请求的纽带角色,这也是我们接下来要介绍的重点。
node做中间层的作用
node做中间层主要有以下作用:

  1. 接收前端发送来的请求,然后进行请求转发,在node层发送真正的后端请求,由于后端是不存在跨域的,所以某种意义上也能解决跨域的问题;
  2. 根据前端的请求信息进行逻辑判断,针对不同形式的请求做相应的处理,比如可以根据请求信息判断是移动端还是PC端发来的请求,以此来确定作何处理;
  3. 对前端请求的数据进行二次处理,然后在node层发送真正的后端请求,同样,对后端请求返回的数据,我们可以进行二次处理,加工成前端需要的数据形式,处理后再由node将数据返回给前端;
  4. 做服务端渲染,有利于SEO,性能也会得到优化;
  5. 浏览器端同时发起多个http请求时,非常耗时,可以通过node给浏览器暴露一个接口,node和真正的后端的多个接口通信,起到合并接口的作用。

3和5应用最广泛的,我在项目里所用到的node中间层也是这个用途。
上点代码简单做一下示例,就用express示范一下,这些常用的框架各位前端同胞应该都比较熟悉 ( 不熟悉的话请自行度娘。。。)
一个简单router的定义:

var express = require('express');
var router = express.Router();
var axios = require('axios');

var url = 'https://***************/*********';
router.get('/', function (req, res, next) {
    res.results = {
        code: 200,
        message: 'getUser request'
    }
    //console.log(req)
    axios.post(url, {}).then(function (response) {
        let {data } = response.data;
        console.log(data)
        res.send(data);
        // 把request和response转交给下一个中间件!!!
        next();
    }).catch(function (err) {
        res.send({error: 'error'});
    });
    //res.render('index', { title: 'daihe' });
    
}, function (req, res, next) {
    console.log(res.results);
    console.log('response success!!');
});

module.exports = router;

引入路由,起node服务器:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var getUserRouter = require('./routes/getUser');
var bodyParser = require('body-parser');/*post方法*/

var app = express();

app.use(bodyParser.json());// 添加json解析
app.use(bodyParser.urlencoded({extended: false}));

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// 路由中间件,引入上面定义的路由
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/getuser', getUserRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

我们组用的是基于express自研的node框架 (其实只是在express的基础上进行了再次封装,用起来更方便些~) 。
业务中的使用场景
最近接触到的业务有这样一个需求:用户设置好商品后点击购买,首先会先创建商品,所有商品都创建成功后,会跳转到下订单的页面,提交订单后会触发创建计算机集群的请求。
于是问题就来了,订单页面不是我们组做的,是两个完全独立的项目代码,但是点击订单页成功下单后会触发创建计算机集群的请求,由于此时的订单页面是其他部门的老铁写的代码,是独立的工程,肯定不受我们的代码控制,因此直接进行常规请求流程是行不通的。可能你已经看晕了,总之简单来说就是以下几个步骤:

  1. 在前端发送创建商品的请求;
  2. 在node层对前端的请求进行包装,进行请求转发;
  3. 创建商品全部成功后跳转到订单页面,提交订单后后台来调用node层的接口;
  4. 用订单系统的请求参数和前端传来的参数拼出新的数据结构,用该参数执行最终的创建请求;
    因为有接口参数需要node层对两次不同请求的参数进行重组,但是在第二个请求发生时,第一个请求的信息已经获取不到了,因此用了redis对第一个请求中有用的信息进行了缓存,在第二个请求发生时就能成功拿到第一个请求的有用信息了。

总结
node.js在最新的前端里扮演着相当重要的角色,也解决了不少曾经很让前端工程师棘手的问题,其实现在的前端和曾经的html+css+js三板斧已经完全不是一种东西了,现在广义上的前端实际上做了很多以前后端来做的工作,比如ajax请求、路由控制,还有我们正在说的node服务,本身就是介于前后端之间的一个中转服务器,node中间层能做无视跨域、接口合并、二次处理前端数据、服务端渲染等工作,把耗性能的操作从前端剥离,对前端是一种很大的优化。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐