nodeJS 学习笔记

187 阅读4分钟

这是一篇学习笔记,主要记录使用node.js完成一个小型服务器的搭建。 web服务框架选用koa,数据库选用MongoDB,数据库操作库选用mongoose,原因是这个以前看过一点有一点印象。

服务器搭建

安装

在自己喜欢的位置创建一个文件夹,然后一路回车

koa-study  npm init

下一步安装koa 官网 Koa (koajs) -- 基于 Node.js 平台的下一代 web 开发框架 | Koajs 中文文档 (bootcss.com)

npm i koa

项目根目录下创建src文件夹创建项目入口文件server.js 先跑一下官网的hello word

// server.js

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);
# 进入src文件夹
cd src/
# 启动node
node server.js

然后访问一下

image.png

路由

开始之前先确定一下做管理台需要什么。

  • 登录注册
  • 管理信息
  • 保存文件

下面做自己的服务器,创建一个app.js。server.js只用来入口文件,app.js作为项目的主文件。

// app.js
const Koa = require('koa')
const app = new Koa();

module.exports = app;
// server.js
const app = require('./app');

const server = app.listen(3030, () => {
  console.log('Server is running at http://localhost:3000');
});

module.exports = server

引入koa-router 懂得都懂不废话了

npm i koa-router

在src下创建route用来管理路由

// src/route/index.js
const Router = require('koa-router');
const router = new Router();

然后我希望这个可以自动扫描所有的路由文件,自动导入。网上借鉴了一下

// 目录结构
src
-route
--index.js
--routes
---login.js
---file.js
---info.js

// src/route/index.js
const fs = require('fs');
const Router = require('koa-router');
const router = new Router();

function initRouter(app) {
  // 先导入fs模块,然后用readdirSync列出文件 这里可以用sync是因为启动时只运行一次,不存在性能问题:
  const files = fs.readdirSync(__dirname + '/routes');
  // 过滤出.js文件:
  const js_files = files.filter((f) => {
    return f.endsWith('.js');
  });

  // 处理每个js文件:
  for (const f of js_files) {
    // 导入js文件:
    const mapping = require(__dirname + '/routes/' + f);
    for (const url in mapping) {
      if (url.startsWith('GET')) {
        // 如果url类似"GET xxx":
        const path = url.substring(4);
        router.get(path, mapping[url]);
      } else if (url.startsWith('POST ')) {
        // 如果url类似"POST xxx":
        const path = url.substring(5);
        router.post(path, mapping[url]);
        console.log(`register POST ${path}-${typeof mapping[url]}`);
      } else {
        // 无效的URL:
        console.log(`invalid URL: ${url}`);
      }
    }
  }
  app.use(router.routes());
}
module.exports = initRouter;

// src/route/routes/login.js
const login = async (ctx) => {
  ctx.response.body = { messag: '这是登录接口' }
}

module.exports = {
  'GET /api/account/login': login,
};

index.js暴露出一个initRouter方法,在app中引入使用

// src/app.js
const Koa = require('koa')
const app = new Koa();
const initRouter = require('./route/index')
initRouter(app);
module.exports = app;

postman跑一下是好使的

11.21.png

MongoDB数据库

下载解压MongoDB 链接

sudo mv mongodb-macos-x86_64-4.2.15/ mongodb

配置环境变量,这里是zsh

先打开bash配置文件

~/.bash_profile
vi ~/.bash_profile

将需要添加的变量在~/.bash_profile中导出

export PATH=${PATH}:/usr/local/mongoDB/bin

这样生效后,bash shell中就有这两个环境变量了 然后打开zsh的配置文件~/.zshrc

vi ~/.zshrc

如果根目录没有.zshrc的话,执行下面的命令

touch ~/.zshrc vi ~/.zshrc

在~/.zshrc最下边添加如下内容:

export PATH=${PATH}:/usr/local/mongoDB/bin

最后退出终端,重新启动,再次进入zsh的时候,会生效配置文件。通过

mongo -version

查看添加的环境变量是否生效。

注意:如果不需要在bash shell中使用环境变量,1,2步骤可以不做,直接在.zshrc中进行修改即可。

创建日志及数据存放的目录

数据存放目录

sudo mkdir -p /usr/local/var/mongodb

日志存放目录

sudo mkdir -p /usr/local/var/log/mongodb

接下来要确保当前用户对以上两个目录有读写的权限
以上 ajiao 是我电脑上的用户,你这边需要根据你当前对用户名来修改

sudo chown ajiao /usr/local/var/mongodb

sudo chown ajiao /usr/local/var/log/mongodb

接下来我们使用以下命令在后台启动 mongodb:

mongod --dbpath /usr/local/var/mongodb --logpath /usr/local/var/log/mongodb/mongo.log --fork
  • --dbpath 设置数据存放目录
  • --logpath 设置日志存放目录
  • --fork 在后台运行

如果不想在后端运行,而是在控制台上查看运行过程可以直接设置配置文件启动:

mongod --config /usr/local/etc/mongod.conf

查看 mongod 服务是否启动:

ps aux | grep -v grep | grep mongod

使用以上命令如果看到有 mongod 的记录表示运行成功。

启动后我们可以使用 mongo 命令打开一个终端:

☁  ~  mongo
MongoDB shell version v5.0.5
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("95fe5c6e-f0fc-460c-88d7-89c3f3d37ddd") }
MongoDB server version: 5.0.5

本节参考菜鸟教程Mac OSX 平台安装 MongoDB | 菜鸟教程 (runoob.com)

mongoose

  • 安装
npm i mongoose --save

在项目中简单的封装一下
在src下新建db文件夹

// src/db/initDB
const mongoose = require('mongoose');

const DB_URL = 'mongodb://localhost:27017/runoob';

mongoose.connect(DB_URL);

mongoose.connection.on('connected', function () {
  console.log('Mongoose connection open to ' + DB_URL);
});

mongoose.connection.on('error', function (err) {
  console.log('Mongoose connection error: ' + err);
});

mongoose.connection.on('disconnected', function () {
  console.log('Mongoose connection disconnected');
});

module.exports = mongoose;
// src/db/index
const m = require('./initDb.js');
const Schema = m.Schema;

class Mongodb {
  constructor(schemaOpt, tableName) {
    let schema = new Schema(schemaOpt)
    this.model = m.model(tableName, schema)
  }
  // 查询
  query(params) {
    return new Promise((resolve, reject) => {
      this.model.find(params, (err, res) => {
        if (err) {
          reject(err);
        }
        resolve(res);
      });
    });
  }
  queryOne(params) {
    return new Promise((resolve, reject) => {
      this.model.findOne(params, (err, res) => {
        if (err) {
          reject(err);
        }
        resolve(res);
      });
    });
  }
  // 保存
  save(obj) {
    const m = new this.model(obj);
    return new Promise((resolve, reject) => {
      m.save((err, res) => {
        if (err) {
          reject(err);
        }
        resolve(res);
        console.log(res);
      });
    });

  }
}
module.exports = Mongodb;

接下来就可以使用了

// src/route/routes/login.js
const userSchma = {
  userName: String,
  passWord: String,
  uuid: String,
}
const DB = require('../../db/index')
const db = new DB(userSchma, 'userTable')
const registe = async (ctx) => {
  const { body } = ctx.request
  // 检查用户名是否存在
  const userName = await db.queryOne({ 'userName': body.userName });
  if (userName) {
    ctx.response.body = { message: '用户名已存在', success: false, code: 400 }
  } else {
    try {
      db.save({
        userName: body.userName,
        password: body.password,
        uuid: tool.createId(),
        createTime: new Date(),
      })
      ctx.response.body = { message: '创建成功', code: 200 }
    } catch (error) {
      ctx.response.status = 500
      ctx.response.body = { message: '服务器开小差了', code: 400 }
    }
  }
}