KOA入门之搭建一个简易账号注册的服务

412 阅读8分钟

前言

前段时间本小白学习了一点nodejs的知识,并了解了如何使用nodejs的koa框架搭建一个后端服务!没错,不需要学习java、python,= =;好吧不尬了,直接上代码!

1、前端

前端用的elementui的组件库,方便简洁= =。(主要是懒得自己再写css调样式,现成的他不香嘛!)

1-1、注册页面:

非常传统,传统的不能再基础的页面-0-,唯一需要稍微看一下的地方就是这个获取验证码按钮还有提交按钮。

1-2、获取验证码按钮

组件样式,由于一般需要倒计时,所以绑了个变量-0-。

<el-button type="primary" @click="getVerifyCode" :disabled="countable" style="margin-left:10px">{{btnctx}}</el-button>

js代码部分,倒计时开始!并且向后端发起短信下发验证码的请求,注意及时清除计时器!

methods:{
    getVerifyCode(){
        this.btnctx = 3;
        this.countable = true
        var ti = setInterval(()=>{
            this.btnctx--;
            if(this.btnctx<1){
                clearInterval(ti);
                this.btnctx = '重新获取验证码';
                this.countable = false
            }
            
        },1000);
        let url = 'http://localhost:1234/gvc?phonenumber='+this.phonenumber
        this.axios.get(url).then(res=>{
            console.log(res.data)
            this.correctCode = res.data.code;
            this.servTimeSnamp = res.data.timp;
        })

    },
}

= =没错服务是搭在1234这个端口的

接下来看提交按钮!

1-3、提交按钮

提交按钮无非就是判断验证码是否相同,这里小白有一个疑问,一般的验证码都是由后端生成的,那么是否需要保存在后端呢,保存的时长怎么处理,包括过期验证码的处理机制等等...看了我上述的代码,就知道我是后端生成了验证码返回到前端,并多了一个时间戳。直接交由前端验证了 = =;

看代码!简单的填入验证码和后端验证码是否正确,以及根据时间戳判断是否超时后,提交表单!重点接下来koa框架搭建的web服务!

methods:{
    upload(){
        var currentTimeSnamp = new Date().getTime();
        if(this.verifycode !== this.correctCode || this.verifycode == ''){
            alert("验证码错误,请重新输入!")
        }else if(currentTimeSnamp-this.servTimeSnamp>5*60*1000){
            alert("验证码失效,请重新获取!")
        }else{
            let url = 'http://www.chrischenny123.com/regist'

            this.axios.post(url,{
                username:this.username,
                pass:this.pass,
                phonenumber:this.phonenumber
            }).then(res=>{
                console.log(res.data)
                alert(res.data)
            }).catch(err=>{
                console.log(err)
            });
        }
        
    }
}

2、后端

本小白在使用koa框架进行web搭建的时候踩过好多坑,有的是对于js的异步机制的不了解,有的是因为对于koa处理请求的机制不了解导致的= =;没错后面可能小白会专门写一篇关于异步的那些事情,万恶的generator、promise以及async await!!!!

2-1、整体框架

由于注册服务也就用到了两个接口,整体的代码不会特别复杂~接下来现简单写一下大致的架构不写具体逻辑!这里我们要用到koa-router来进行路由接口,以及koa-bodyparser来进行post的数据解析!

var Koa = require('koa')
var router = require('koa-router')(); //注意后面的括号。
var bodyparser = require('koa-bodyparser');

var app = new Koa();

router.get('/gvc',async (ctx)=>{//获取验证码、下发短信接口
    consloe.log('获取验证码!');
    ctx.body = 200;
}
router.post('/regist',async ctx=>{//注册用户接口
    console.log('注册成功!');
    ctx.body = 200;
}
app.use(async (ctx,next)=>{//设置cors
    ctx.set("Access-Control-Allow-Origin", "*");
    ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
    ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
    if(ctx.method == 'OPTIONS'){//处理跨域预请求
        ctx.body = 200;
    }else{
        await next();
    }
    
})
app.use(bodyparser());//bodyparser需要在router前调用。
app.use(router.routes());
app.listen(1234);

这样就处理完大致的架构了,包括设置了cors,解决跨域的问题! koa的回调函数的参数ctx就是将http请求的respone和request集合到一起~

2-2-1、验证码生成、短信下发接口

验证码的生成无非就是random函数的调用吧,嘿嘿。 另外短信下发的话,还是要和运营商的接口做联调,我这里用的是联通的创新能力平台的企业短信能力接口。接口文档联通创新能力平台都有,自己去看吧嘿嘿,记得好像要企业认证(相信你能搞定嘿嘿),有免费300条的短信体验,剩下当然是要money的!不过肯定比外面的短信服务便宜吧!

回到正题!有了联通创新平台短信能力的接口,接下来就是解决和联通服务器的接口联调了!本小白用的是reque-promise的这个模块,比较契合koa(因为koa也是一个web异步框架)

话不多说!上代码!

var request = require('request-promise');
var cryoto = require('crypto');
const USER = '1234'
const SECRET = '1234'//注册账号后获得~

router.get('/gvc',async (ctx)=>{
    var num  = ctx.query.phonenumber//获取前端传来的号码
    var tick = new Date().getTime();//获取时间戳
    var key = cryoto.createHash('md5').update(USER+tick+SECRET).digest('hex').slice(0,16);//md5hash
    var c = Math.floor(Math.random()*1000000).toString();生成验证码!
    console.log(key);
    var options = {//request-promise的入参对象,详细参数介绍---看接口文档,嘿嘿
        url:'http://123.125.99.240:501/send',
        qs:{//qs在request-promise处理后会自动拼接到url后
            user:USER,
            tick,
            key,
            tid:"01",
            m:num,
            c,
        }
    }
    var Req = request(options);//获得请求的promise对象。
    let state = await Req;//等待接口请求结束后获取联通侧返回的状态对象
    console.log(state);
    if(state.code === '1'){
        ctx.body = {//设置返回前端的json对象
            code:c,
            timp:tick
        };
    }else{
        ctx.body = 'failed!'//参数对了基本不会有问题,可能存在超时,也可以递归再请求一次= =;
    }
});

到这里,基本的获取验证码+用户短信下发的接口就完成了!接下来就是用户注册接口的实现了,我们的小服务端已经完成一大半了!!

2-3-1、用户注册接口实现

既然是用户注册,那么肯定少不了数据库 = =; 小白用的当然是免费的mysql数据库,那么koa想要操作数据库,肯定也是需要中间件,那么隆重请出!nodejs的中间件mysql-0-,与数据库同名,好无聊。看一下简单的实现

var mysql = require('mysql');
var sql = 'SELECT * FROM Table'
var db = mysql.createConnection({//数据库相关的参数
    host : 'localhost',
    user:'root',
    password:'111',
    database:'test'
});
db.connect();//创建链接
db.query(sql,(err,result)=>{})//调用该方法操作数据库。

这个中间件有一个小毛病,也不能说是毛病,但是很蛋疼,就是连接后每8小时如果没有查询等操作就会自动断开 = =; 稍微改造一下上面的代码,侦听一下err,并重连。

var connect = function(){
    db = mysql.createConnection({
        host : 'localhost',
        user:'root',
        password:'111',
        database:'test'
    });
    db.connect(err=>{//连接数据库
        if(err){
            setTimeout(connect,2000)
        }
    });
    db.on('error',(err)=>{//侦听错误,并递归调用该函数
        if(err.code === 'PROTOCOL_CONNECTION_LOST'){//超时错误码
            connect();
        }else{
            console.log(err)
        }
    })
}

connect();

OK!这样就不会有问题了! 接下来看我们的注册接口的代码!

var mysql = require('mysql');

var connect = function(){
    db = mysql.createConnection({
        host : 'localhost',
        user:'root',
        password:'111',
        database:'test'
    });
    db.connect(err=>{//连接数据库
        if(err){
            setTimeout(connect,2000)
        }
    });
    db.on('error',(err)=>{//侦听错误,并递归调用该函数
        if(err.code === 'PROTOCOL_CONNECTION_LOST'){//超时错误码
            connect();
        }else{
            console.log(err)
        }
    })
}

connect();

router.post('/regist',async ctx=>{
    var userinfo = ctx.request.body;//通过koa-bodyparser处理过的数据都会存在这个属性中
    //数据库操作语句!
    var sql = `INSERT INTO userinfo VALUES ('${userinfo.username}','${userinfo.pass}','${userinfo.phonenumber}')`;
    var result = new Promise(function(reslove,reject){
        db.query(sql,(err,result)=>{
            if(err){
                reject(err)
            }
            console.log(result);
            reslove("success");
        })
    });
    ctx.body = await result;
})

写在后面的话

到这里就结束了!这里面有个小坑~我们可以看到实际db.query(sql,cb)是有一个回调函数的,为什么我们不直接在回调函数里面直接设置ctx.body呢?这里就涉及到koa框架的工作原理了,不少童鞋用过express框架知道我们可以直接在回调函数里面设置res.send()

但是koa不一样= =;,koa根据代码顺序执行完所有中间件之后就会直接返回前端ctx.body,而在这个时候,回调函数还没有执行(这个就涉及到nodejs的eventloop的问题了!)所以定义在回调函数里面的ctx.body当然就不起效了!

本小白开始的时候完全不了解这些机制,踩了不少坑!才从这个回调地狱中走出来,所以上述例子中,才将db.query封装成promise,用await强制等待执行完毕然后处理ctx.body。后续我也会单独写一篇关于js、nodejs关于eventloop,以及异步编程的文章,温故知新一下!

写在最最后面的话

本小白的第一篇文章,没什么技术含量!就是对自己一段时间的总结和回顾,里面可能有好多地方写的有问题!希望大佬们多多指出!我及时改正!完整的代码还在整理,木有上传github,可能后面集成到一个小项目的时候会放到github上面~

写在最最最后面的话

小小打个广告,有大佬们需要短信业务,或者号码认证的能力的话,可以看看这里!中国联通创新能力平台 运营商自己的平台,价格会比外边低一些吧!