最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • redis在Node中的简易应用

    正文概述 掘金(MrGaoGang)   2021-02-23   563

    在编写【日程安排吧】微信小程序中有使用到 redis 进行缓存,刚好有同学问道如何在node中使用redis;现简单介绍一下在 nodejs 中如何使用 redis,以及如何对 redis 的读取进行简单的封装。

    环境准备

    在 node 中使用 redis 的前提是您的主机装有 redis;其安装方式如下:

    • centos 安装 redis
    # 安装Redis
    sudo yum -y install redis
    # 启动redis
    sudo systemctl start redis
    # 给Redis设置密码,取消注释如下这一行
    #requirepass foobared
    requirepass 密码
    
    # 重启
    sudo systemctl restart redis
    
    
    # 其他
    systemctl start redis.service #启动redis服务器
    
    systemctl stop redis.service #停止redis服务器
    
    systemctl restart redis.service #重新启动redis服务器
    
    systemctl status redis.service #获取redis服务器的运行状态
    
    systemctl enable redis.service #开机启动redis服务器
    
    systemctl disable redis.service #开机禁用redis服务器
    
    
    
    • mac 安装 redis
    # 安装
    brew install redis
    
    # 1. 启动redis
    brew services start redis
    
    # 2.关闭redis服务
    
    brew services stop redis
    # 3.重启redis服务
    
    brew services restart redis
    
    # redis的配合文件地址: /usr/local/etc/redis.conf
    vim /usr/local/etc/redis.conf
    
    # 修改密码
    requirepass 密码
    # 重启
    brew services restart redis
    
    

    安装完成 redis 后,您就可以在项目工程下运行如下命令:

    npm install redis
    # 如果有typescript的同学,可以安装如下依赖
    npm install --save-dev @types/redis
    

    对 redis 的简单封装

    我们先说说简单的使用吧,在 nodejs 中使用 redis 其实是比较简单的,创建一个 client,然后进行读取和写入的操作;

    import * as Redis from "redis";
    const client = Redis.createClient({
      host: "localhost",
      port: 6379,
    });
    
    //连接错误处理
    client.on("error", (err) => {
      console.log("redis connect err", err);
    });
    
    client.on("connect", () => {
      console.info("redis connect success");
    });
    // 一个简单的数据存储
    client.set("travel:i-wants", "{a:1}", function(err, result) {});
    client.get("travel:i-wants", function(err, result) {
      console.log(result);
    });
    

    通过如上的代码我们发现如下几个问题:

    1. redis npm 版本,读取和存储使用的是回调函数方式; 【解决办法】我们可以转换成 promise 的形式;
    2. 对数据的存取每次都需要分别处理错误和正常的情况; 【解决办法】统一处理错误和数据封装
    3. 每次对存取数据需要写一堆 key【解决办法】key 统一提炼为常量

    改造之后的代码:

    import * as Redis from "redis";
    const client = Redis.createClient({
      host: "localhost",
      port: 6379,
    });
    
    //连接错误处理
    client.on("error", (err) => {
      console.log("redis connect err", err);
    });
    
    client.on("connect", () => {
      console.info("redis connect success");
    });
    
    type RedisHelperBase = {
      setData: (key: string, value: any, expire?: number) => Promise<any>;
      getData: (key: string) => Promise<any>;
    };
    //  统一处理promise的正确和错误,使用时 直接这样使用即可const [error,data] = await xxxx(); 摆脱.then .catch
    function awaitWrap<T, U = any>(
      promise: Promise<T>
    ): Promise<[U | null, T | null]> {
      return promise
        .then<[null, T]>((data: T) => [null, data])
        .catch<[U, null]>((err) => [err, null]);
    }
    // 统一封装redis数据的存和取
    const redisHelper: RedisHelperBase = {
      /**
       *
       * @param key key
       * @param value 值
       * @param expire 默认为5分钟
       */
      setData: (key, value, expire = 60 * 5) => {
        return awaitWrap( // 外层统一处理promise的then和.catch情况
          new Promise((resolve, reject) => {
            // 我这里存储的数据为string,如果是对象类型则进行转换,其实这里使用typeof value === "object" 判断也不完全正确
            client.set(
              key,
              typeof value === "object" ? JSON.stringify(value) : value,
              function (err, result) {
                if (err) {
                  reject(err);
                }
                // 如果传递过期时间,那么就对指定的key的数据设置过期
                if (!isNaN(expire) && expire > 0) {
                  client.expire(key, expire);
                }
                resolve(result);
              }
            );
          })
        );
      },
      getData: (key) => {
        return awaitWrap( // 外层统一处理promise的then和.catch情况
          new Promise((resolve, reject) => {
            client.get(key, function (err, result) {
              if (err) {
                reject(err);
              }
              if (result) {
                try {
                  // 对数据进行解析,如果是非object的话,就直接返回内容,否则进行数据解析为Object
                  resolve(JSON.parse(result));
                } catch (error) {
                  resolve(result);
                }
              } else {
                resolve(result);
              }
            });
          })
        );
      },
    };
    
    export { redisHelper };
    
    export default redisHelper;
    
    export * from "./const";
    
    

    在实际业务中使用

    上述我们已经简单封装了 redis 的存储,下面简单介绍一下在业务中如何使用:

    以【日程安排吧】小程序中的【想要的功能】查询和删除为例:

    // 数据的查询
    export async function query(ctx: BaseContext<{ status?: string }>) {
      // ...请求的参数
      // 先从redis中读取,分为两个参数,第一个参数为是否error,第二个为具体的内容
      const [error, data] = await redisHelper.getData(wantRedisKey(status));
      // 如果报错或者有没有数据就查询一下数据库
      if (error || (!error && !data)) {
        const result = await sequelize.transaction(async () => {
          return await WantsModel.findAll({
            // ...
          });
        });
        responseSuccess(ctx, result);
        // 数据同步到redis中
        await redisHelper.setData(wantRedisKey(status), result);
      } else {
        responseSuccess(ctx, data);
      }
    }
    
    // 数据的删除
    export async function deleteItem(
      ctx: BaseContext<{ status?: string, id?: string }>
    ) {
      // ...请求的参数
      // 先从缓存中读取
      const [error, wantList] = await redisHelper.getData(wantRedisKey());
      let hasRedisDelete = 0;
      // 删除的时候 删除缓存内的数据,提前将缓存内的数据返回给用户
      if (!error && wantList && Array.isArray(wantList)) {
        const index = wantList.findIndex((ele: any) => ele.id === id);
        if (index !== -1) {
          responseSuccess(ctx, wantList[index]);
          wantList.splice(index, 1);
          hasRedisDelete = 1;
          // 更新数据
          await redisHelper.setData(wantRedisKey(), wantList);
        }
      }
    
      const result = await sequelize.transaction(async () => {
        return await WantsModel.findOne({
          where: {
            // ....
          },
        });
      });
      if (result !== null) {
        // 此处也可以设计为软删除,我这边这个直接是硬删除了
        result.destroy();
        // 没有使用redis的情况,直接返回数据
        !hasRedisDelete && responseSuccess(ctx, result);
      } else {
        responseError(ctx, "数据删除失败,没有查询到此数据");
      }
    }
    

    至此一个简单的 redis 在 Nodejs 中使用已经介绍完毕,至于 redis 其他的高级用法详情可见 github: redis


    起源地下载网 » redis在Node中的简易应用

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元