node.js redis同期取値bluebird async await promisifyAll

9581 ワード

1.redisライブラリのインストール
npm install --save redis
2. ../../.../config.js
module.exports = {
    // ...
    redis: {
        host: "172.16.0.224",
        port: 6379,
        options: {
            password: "myredispassword",
            timeout: 3000
        }
    },
    spam: {
        limit: 3,
        seconds: 60,
    },
    // ...
}

3. Cache.js
const redis = require("redis");
const config = require("../config/config");

let c = config.redis,
    client = redis.createClient(c.port, c.host, c.options);

client.on("error",function(err){
    console.log(err);
});

function Cache() {}

let text = async(key)=>{
    let doc = await new Promise( (resolve) => {
        client.get(key,function(err, res){
            return resolve(res);
        });
    });
    return JSON.parse(doc);
};

Cache.set = function(key, value) {
    value = JSON.stringify(value);
    return client.set(key, value, function(err){
        if (err) {
            console.error(err);
        }
    });
};

Cache.get = async(key)=>{
    return await text(key);
};

Cache.expire = function(key, time) {
    return client.expire(key, time);
};

module.exports = Cache;

Usage:
    // begin       
    let ip = Client.getIP(req);
    let key = "mail:" + ip;
    let ans = await Cache.get(key);

    let count = 0;
    if (ans) {
        logger.debug(ans);
        count = parseInt(ans);
    }
    count++;
    Cache.set(key, count);
    //        
    Cache.expire(key, config.spam.seconds);

    if (count > config.spam.limit) {
        res.json({
            code: 16,
            data: count,
            message: "     "
        });
        return;
    }
    // end       

 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
もう一つの方法bluebird
使用するライブラリ:
http://bluebirdjs.com/docs/getting-started.html
 
* ./config/cache.js
redis構成
module.exports = function() {
    return {
        session: {
            host: "172.16.0.224",
            port: 6379,
            option: {
                password: "Mzh123",
                db: 0,
                connect_timeout: 500,
            }
        },
        app: {
            host: "172.16.0.224",
            port: 6379,
            option: {
                password: "Mzh123",
                db: 1,
                connect_timeout: 500,
            }
        }
    };
};

* ./providers/Redis.js
const redis = require("redis");
const cacheConfig = require("../config/cache")();
const bluebird = require('bluebird');

function Redis() {}

/**
 *
 * @type {{session: null|RedisClient}}
 * @private
 */
Redis._connection = {
    "session": undefined,
    "app": undefined,
};

Redis.getConnection = function(name) {
    name = name || "session";
    if ( Redis._connection[name] ) {
        return Redis._connection[name];
    }

    let opt = cacheConfig[ name ];
    let client = redis.createClient(opt.port, opt.host, opt.option);
    client.on('connect', function() {
        console.log('Redis connected.')
    });
    client = bluebird.promisifyAll(client);
    Redis._connection[name] = client;

    return Redis._connection[name];
};

module.exports = Redis;

キーコード:
client = bluebird.promisifyAll(client);

promisifyAllの後にクライアントに値を再割り当てします
 
* ./app/controllers/Middleware.js
'use strict';

var jwt = require('jsonwebtoken');
// var koaJwt = require('koa-jwt');
var constants = require('../../config/const');
var Redis = require('../../providers/Redis');

function Middleware() {}

Middleware.hasBody = async (ctx, next) => {
    let body = ctx.request.body || {};
    console.log(body);

    if (Object.keys(body).length === 0) {
        ctx.body = {
            code: 2,
            err: '  '
        };

        return next
    }
    await next()
};

//   token
Middleware.hasToken = async (ctx, next) => {
    var accessToken = ctx.headers.token;

    if (!accessToken) {
        accessToken = ctx.request.body['token'];
    }

    if (!accessToken) {
        ctx.body = {
            code: 4,
            data: null,
            message: 'Token missing'
        };
        return next
    }

    // :{"userid":"5cc7f30396e85920c0c5b885","username":"mingzhanghui","iat":1556609542,"exp":1556609602}
    let c = constants();
    let tokenContext = jwt.decode(accessToken);
    /**
     * @type RedisClient
     */
    let cache = Redis.getConnection('session');
    let key = c.session_prefix + tokenContext.userid;
    console.log(key);
    // if (+new Date() >= c.exp * 1000) {
    const res = await cache.getAsync( key );
    if (! res) {
        ctx.body = {
            code: 5,
            data: null,
            message: 'Token expired',
        };
        return
    }
    let sess = JSON.parse(res);
    console.log(sess);

    ctx.session.user = {
        id: sess.userid,
        name:sess.username
    };
    await next();
};

module.exports = Middleware;

 
ブルーバードのPromisifyAllを使ったのでgetメソッドによってgetAsyncができました
await cache.get(key, function(err, res) {
 //...
})
ここではboolタイプを返し、所望のredisではなく結果を返します.
const res=await cacheに変更します.getAsync( key );
これでresはredisの戻り結果です
 
* router.js
'use strict';

const Router = require('koa-router');
const Middleware = require('./app/controllers/middleware');
const UserController = require('./app/controllers/UserController');
const TestController = require('./app/controllers/TestController');

module.exports = function(){
  var router = new Router({
      prefix: ''   /* /api */
  });

  router.get('/ping', async function(ctx, next) {
      ctx.body = {
          "code": 0,
          "data": null,
          "message": "pong"
      };
      ctx.contentType = 'application/json';
  });

  // user
  router.post("/users/login", Middleware.hasBody, (new UserController()).login);
  // need login  middleware.hasToken
  router.get('/users/getInfo', Middleware.hasToken, (new UserController()).getInfo);
  router.get('/users/logout', Middleware.hasToken, (new UserController()).logout);

  router.post('/users/signup', Middleware.hasBody, (new UserController()).signup);

  router.post('/users/update', Middleware.hasBody, (new UserController()).update);
  // router.get('/users/delete', (new UserController()).delete);
  // DB Interface test
  router.get('/users/all', (new UserController()).all);

  router.get('/test', (new TestController()).date);

  return router
};

* ./app/controllers/UserController.js
 
/**
 *       
 * @param ctx
 * @param next
 * @returns {Promise}
 */
UserController.prototype.getInfo = async function(ctx, next) {
    // let token = ctx.headers.token;
    let userid = ctx.session.user.id;
    console.log("userid=" + userid);
    if (!userid) {
        ctx.body = {
            code: -1,
            data: null,
            message: "Redis get error"
        };
        return;
    }

    await Users.findOne({"_id": userid}).exec().then(function (doc) {
        if (!doc) {
            ctx.body = {
                code: 2,
                data: doc,
                message: "User not found"
            };
            return;
        }
        ctx.body = {
            code:0,
            data: doc,
            message: "OK"
        };
    });

};

 
mongodb:
* ./config/db.js
module.exports = function() {
    return {
        default: 'mongodb://eclassuser:[email protected]/crm_sale'
    };
};

* ./app/models/mongoose.js
"use strict";

const bluebird = require('bluebird');
const Mongoose = require('mongoose');

const dbDefaultURI = require('../../config/db.js')().default;

let mongoose = bluebird.promisifyAll(Mongoose);
let defaultMongooseConn = mongoose.createConnection(dbDefaultURI);

defaultMongooseConn.on('error', function(err) {
    // logger.error(err);
    console.error(err);
});

module.exports = {
    mongoose: mongoose,
    defaultMongooseConn: defaultMongooseConn
};

* ./app/models/Users.js
"use strict";

let m = require("./mongoose");
const mongoose = m.mongoose;
const defaultMongooseConn = m.defaultMongooseConn;

var Schema = mongoose.Schema;

var schema = new Schema({
    username: {type: String, required: true},
    password: {type: String},
    createdAt: {type: Date, default: Date.now()},
    updatedAt: {type: Date, default: Date.now()},
});
schema.index({username: 1}, {unique: true});

// Defines a pre hook for the document.
schema.pre('save', function(next) {
    if (this.isNew) {
        this.createdAt = this.updatedAt = Date.now()
    }
    else {
        this.updatedAt = Date.now()
    }
    next()
});

var Users = defaultMongooseConn.model('users', schema);

module.exports = Users;