ChenJiaH / blog

📝个人博客 - 欢迎关注 👀 和点赞 ⭐️
https://chenjiahao.xyz/blog
MIT License
9 stars 7 forks source link

Nodejs+Express+Mongodb搭建简单的应用 #10

Open ChenJiaH opened 5 years ago

ChenJiaH commented 5 years ago

首发于微信公众号《前端成长记》,写于 2016.04.27

Nodejs 介绍

Node.js应用场景

高并发、高性能服务器

Node.js最重要特性

通过单线程实现异步处理环境

实现高性能的两种机制

一. 非阻塞型I/O

在执行访问数据库的代码之后可以立即转而执行后面的代码,把数据库返回结果的处理代码放在回调函数中执行。(传统阻塞型I/O表现为在执行访问数据库的代码后,线程将暂停下来,等待数据库返回结果再继续执行)

二. 事件环

在一个时刻只能执行一个事件回调函数,但是在执行一个事件回调的中途可以转而处理其他事件(包括触发新的事件、声明该事件的回调函数等),然后返回继续执行原事件回调函数

Node.js v0.10中的核心模块

模块名 模块功能 stability(稳定度)
assert 为应用程序的单元测试添加断言处理 5-Locked(今后不会被修改)
buffer 用于实现二进制数据的存储与转换 3-stable(稳定)
child_process 用于实现子进程的创建与管理 3-stable(稳定)
cluster 用于实现多进程 1-Experimental(实验性阶段)
console 用于为控制台输出信息 4-API Frozen(今后API部分不会被修改)
crypto 用于实现数据的加密解密处理 2-Unstable(不稳定)
debugger 用于实现一个内置调试器来帮助开发者调试应用程序 3-stable(稳定)
dns 用于实现与DNS相关的处理 3-stable(稳定)
domain 用于实现多个I/O之间的协作处理 2-Unstable(不稳定)
events 用于为事件处理提供一个基础类 4-API Frozen(今后API部分不会被修改)
fs 用于操作文件及文件系统 3-stable(稳定)
http 用于实现HTTP服务器端及客户端 3-stable(稳定)
https 用于实现HTTPS服务器端及客户端 3-stable(稳定)
net 用于创建TCP服务器与客户端 3-stable(稳定)
os 用于获取操作系统信息 4-API Frozen(今后API部分不会被修改)
path 用于处理文件路径 3-stable(稳定)
punycode 用于实现Punycode字符串的编码及解码 2-Unstable(不稳定)
querystring 用于处理HTTP请求中使用的查询字符串 3-stable(稳定)
readline 用于读取一行标准输入流 2-Unstable(不稳定)
repl 用于实现REPL(Read-Eval-Print-Loop)交互式运行环境 (无)
stream 用于为流的输入/输出处理提供一个基础类 2-Unstable(不稳定)
string_decoder 用于实现从二进制数据到字符串数据之间的转换 3-stable(稳定)
tls 用于使用OpenSSL来实现TLS/SSL通信处理 3-stable(稳定)
tty 用于获取来自于TTY终端的信息 2-Unstable(不稳定)
url 用于实现URL字符串的解析与格式化 3-stable(稳定)
util 用于实现各种实用函数 5-Locked(今后不会被修改)
vm 用于为Javascript脚本代码提供一个独立的运行环境 2-Unstable(不稳定)
zlib 内部使用zlib类库来实现数据的压缩及解压处理 3-stable(稳定)

Node.js v0.10中追加的类、函数与对象

类、函数及对象名 描述
Buffer类 用于为二进制数据的存储提供一个缓存区
setTimeout函数 用于在制定时间到达时执行一个指定函数,指定方法为从当前时刻之后多少毫秒
clearTimeout函数 用于取消在setTimeout函数内指定的函数的执行
setInterval函数 用于指定每隔多少时间执行一个指定函数
clearInterval函数 用于取消在setInterval函数内指定的函数的执行
require函数 用于加载模块
module对象 用于访问信息模块
process对象 用于访问进程信息

一个简单的栗子(demo)

先在node项目中建立一个demo.js,代码如下:

var http = require('http');
    http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<head><meta charset="utf-8" /></head>');
    res.end("<div style='font-size: 50px;'>I'm McChen</div>");
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

然后在命令行中执行node demo.js

node .\demo.js
//Tips: 命令行中将显示 Server running at http://127.0.0.1:1337/

在任意浏览器打开 http://127.0.0.1:1337/ ,将发现页面中会显示 I'm McChen

开发前准备

非 Webstorm 开发

  1. 创建一个 express 项目
express --sessions newProject
  1. package.json 进行编辑,主要是依赖 dependencies
{
    "name": "newProject",
    "version": "0.0.1",
    "private": true,
    "scripts": {
        "start": "node app.js"
    },
    `"dependencies": {
        "express": "3.4.8",
        "jade": "*"
    }
}
  1. 安装依赖,完成之后执行 node app.js
npm install // or cnpm install

浏览器打开localhost:3000即可发现一个简单express页面建立完成了

  1. 配置入口文件及express参数

在app.js最后面加上下面代码,实例化Express并赋值给app变量

var app = express()

接着对express的参数进行配置,这里设置了端口,寻找views的目录,用什么模板引擎来处理这些views,和一些其它的东西。还要注意最后一行,它告诉Express把public/目录下的静态文件作为顶层目录的文件来托管。

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

继续增加插件检查和过期提醒

// 替换前
app.use(express.bodyParser());
// 替换后
app.use(express.urlencoded());

创建一个http server并且启动它

app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

webstorm 开发

直接new一个新Node.js Express App 项目,直接搞定上面全部流程

Mongodb安装连接

安装 Mongodb 后在 bin 文件目录下执行:

mongod --dbpath D:\database

表示把数据保存在D盘database文件夹下。然后新开一个cmd进入bin文件夹后,执行:

mongo

这时候表示已经连接上了数据库,接下来就可以进行操作了。 首先新建一个属于自己的数据库,并写入数据:

use myDataBase
db.myCollection.insert({ “username” : “XXX″, “email” : “XXX” })

db表示刚才创建的myDataBase的数据库,myCollection表示在里面创建了一张表,后面是插入的字段

把mongo连接到node

在app.js中插入以下代码

app.get('/myDataBase', routes.myDataBase(db));  // 当用户访问myDataBase时,把db传递到路由
router.myDataBase= function(db) {   // 创建对应的myDataBase路由
   return function(req, res) {
      var collection = db.get('myCollection');
       collection.find({},{},function(e,docs){
           res.render('myPage', {
                "data" : docs
           });
       });
   };
};

创建对应的模板,我这里采用的是jade,即myPage.jade(由于不习惯,后期我切换为artTemplate了)

doctype html
html
  head
    title= "McChen"
    link(rel='icon', href='http://www.jd.com/favicon.ico')
    link(rel='stylesheet', href='http://static.360buyimg.com/finance/mobile/base/cm/1.0.0/reset.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
    script(src="/javascripts/test.js")
  body
    h1 McChen
    p.name.title Learning Node
    p.name: #{data[0].username}

保存文件,重启node服务器,你会发现data[0]=XXX,已经从数据库中成功取出来了。往数据库中写入数据,可以通过ajax,然后render数据库的数据。

接下来让我们做一个简单的登录页吧。

搭建简单的登录页

最终效果

image

项目文件结构

先把文件结构贴出来利于后续流程说明

image

步骤

  1. 首先新建一个login.jade文件,代码如下(注意缩进,间隔为2字间距,md不缩进-_-!)
extends layout
block link
    link(rel='stylesheet', href='/stylesheets/1.0.0/login.css')
block content
    canvas#jm-funnyBackground
    div.loginBox.abs-mt
        div.title
           h3
        div.u-name
            h4 用户名:
            input.username#Name(tabindex='1', placeholder='请输入用户名',name='Name', type='text')
        div.u-pwd
            h4 密码:
            input.password#Password(tabindex='2', placeholder='请输入密码',name='Password', type='password')
            a.logon#Logon(href='javascript:;') 登录
block script
    script(src='/javascripts/modules/funnyBackground/funnyBackground.js')
    script(src='/javascripts/modules/login/login.js')

extend是jade模板的一大特色,继承,另外一大特色是mixin,以后再叙(实际项目我已经更换为artTemplate了)。

  1. 编写对应scss和js并引入

  2. 根据上一篇文章,开两个cmd,一个mongod –dbpath D:\database,另外一个mongo。

image

  1. 交互

login.js 截取部分交互代码

self.getAjaxData("/login",{username: username,password:password},"post","json",self.loginCallback)  // 发ajax请求到localhost:3000/login
   loginCallback: function (data) {  // ajax成功回调
       if(data.code == 200){
           window.location = '/index';
       } else if(data.code == 201) {
           alert("您输入的用户名或密码不正确");
       }
   },
   getAjaxData: function (url, data, type, dataType, callback, failFn) {
       $.ajax({
           url: url,
           data: data,
           type: type,
           dataType: dataType,
           success: function (data) {
               callback && callback(data);
           },
           error: function () {
               failFn && failFn();
           }
       });
   }
router.post('/login', function (req, res, next) {
    // 请求带过来的data在req.body里
    var username = req.body.username;
    var password = req.body.password;
    var collection = db.get('usercollection'); //获得数据库中的集合(类似关系数据库中的表)
    collection.find({"username": username, "password": password}, {}, function (e, docs) { //取得所有的集合数据, 渲染到页面上,关键字是data,第一个{}表示where,第二个{}表示显示隐藏,第三个为回调函数
        if (docs != "") {
            req.session.username = docs[0].username;
            req.session.password = docs[0].password;
            res.send({"code": 200});    // 200 表示登录成功
        } else {
            res.send({"code": 201});    // 201 表示登录失败
        }
    });
});
*GET index page */
router.get('/index', function (req, res, next) {
    var docs = res.session;
    res.render('index', {
        "data": docs
    });
});

因为express4.X以上已经把session模块分离出来了,所以必须要多引入依赖模块express-session

在app.js中增加

var session = require('express-session');
app.use(session({
    secret: "McChen",  // 必填参数,可随意取名
    name: "loginMes", // 存入cookies的参数名
    cookie: {maxAge: 60000 * 60 * 24 * 15},  // cookie的生命周期
    resave: false,  // 必须,否则session会报错
    saveUninitialized: true  必须,否则session会报错
}));

之后便可以愉快的利用res.session进行存储了

结束

至此,一个与数据库交互的登录页面已经基本完成

(完)


本文为原创文章,可能会更新知识点及修正错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验 如果能给您带去些许帮助,欢迎 ⭐️star 或 ✏️ fork (转载请注明出处:https://chenjiahao.xyz)