用typescript搭建node.js服务器

鲜于俊侠
2023-12-01

近日为实现cocos creator开发的游戏中实现网络访问功能,比如排行榜、存储游戏成绩等等功能,采用typescript语法,搭建了node.js服务器,为保证可扩展性和一定安全性,在node.js前面用nginx做负载均衡。后端用elastic search做数据库实现排序功能。花了几天时间,排了不少坑。

总体设计的考虑:

一、语法一致性

无论cocos creator还是node.js都采用typescript,采用一样的语言,这样代码前后台一致易于维护。

二、typescript语法严谨

typescript语言本身具有面向对象和强类型定义,比javascript更加优秀,出错可能性,代码的可维护性更强。这也是cocos最终采用typescript原因。

三、避免数据库直通

这种方式,采用一层比较薄的应用层。封装了对后台数据库访问,防止数据库负载过重和保证数据库不直接面对终端。具有一定安全性。

四、采用 post api测试web api能力

因为全web api方式可以用 apipost7软件测试每个服务准确性,甚至性能测试。

解决的系列问题

一、node.js搭建服务器

采用express组件搭建node.js,在代码中首先要安装并在代码中引用:

1.安装最新代码,在项目目录的命令行下键入:

npm install express

2. ts代码中引用方法:

import express from 'express';
import { Application } from 'express';

3. 定义访问类(在自己网络访问类下面定义类,具体形式可根据各自代码区分下):

private app: Application = express();

二、实现hello world

直接上代码(访问http://127.0.0.1:8081/,返回hello world):

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

侦听8081,启动服务:

        let server = this.app.listen(8081, function () {
            let host = server.address();
            console.log("应用实例访问地址为 %s", host)
        });

三、web跨域调用问题

如果cocos creator通过web测试或者直接发布web应用,在访问node.js服务器必然面对跨域调用,会导致访问失败,这是必须在node.js中对每个请求先返回允许跨域的头,具体代码如下:

        // 允许跨域
        this.app.all('*', function (req, res, next) {
            res.header("Access-Control-Allow-Origin", req.headers.origin);
            res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
            res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
            res.header("Access-Control-Allow-Credentials", "true");
            if (req.method === "OPTIONS") res.sendStatus(200);/*让options请求快速返回*/
            else next();
        });

四、设置参数解析方法

因为客户端的访问方式多样,get/post等等,具体的入参编码方式不同,必须前后端一直,比如采用urlencoded:

        // 拦截所有请求 urlencoded()里的参数是必填的
        // extended:false表示方法内部使用querystring模块处理请求参数的格式
        // extended:true表示方法内部使用第三方模块qs处理请求参数的格式
        // 默认使用extended:false即可满足我们的需求
        this.app.use(bodyParser.urlencoded({ extended: false }));

也可以采用json格式,这种格式表达能力最强:

    this.app.use(express.json());

五、post方法接收参数

post方法参数接收比较特殊,因为作为服务器可能会多次分段传输,这里提供两种方法。

  1. 异步直接侦听,采用多次获取方式,最终获得post完整参数。例如:

app.post('/', function(request, response) {

    // push the data to body
    var body = [];
    request.on('data', (chunk) => {
      body.push(chunk);
    }).on('end', () => {
      // on end of data, perform necessary action
      body = Buffer.concat(body).toString();
      response.write(request.body.user);
      response.end();
    });
});
  1. 直接异步实现,将function改为()=>写法,就一次获取所有post数据:

    this.app.post('/', (req, res) => {
         console.log(req.body);
      });

六、node.js中访问web api

在接受了客户端的请求后,往往需要继续访问内部的web服务,这时候需要选择网络的api,这里以最常见的axios为例:

  1. 安装

npm install axios
  1. 引用

import axios, { AxiosInstance } from "axios";
  1. 使用,可以采用两种方式,一种是直接使用axios,如:

axios.request({
            url: 'http://127.0.0.1/test',
            data: data,
            headers: {
                'Content-Type': 'application/json'
            },
            method: 'post'
 }).then((res: any) => {
            if (successCallback != null) {
                successCallback(res);
            }
        })

或者创建自己的类:

    private axiosInstance:AxiosInstance;
        this.axiosInstance = axios.create();

之后的访问同axios。

  1. axios的版本问题,在axios的高版本中对json文本做了缩写,将回车换行全部替换,可能会导致某些web api访问故障,因此解决办法就是采用较低版本,如0.19,这时候需要,卸载原来的axios版本,并安装指定版本:

npm install axios@0.19

 类似资料: