#每天都是崭新的一天#再累也要照顾好自己

songEagle开发系列:如何让文章实时保存的问题

 一、写在前面

如何实现文章的实时保存?一般写文章的写博客的网站都会有这个功能点,这样保证了用户在不小心退出的情况下数据的保存下来,这样的交互比较符合用户的使用心理学。对于用户来说这是一个非常实用的功能,作为一个博客来说,有这个还是不错的。哈哈^_^

songEagle一个新的小窝: http://www.chengxinsong.cn


二、实现的思路

一个功能的实现,你的编程思路很重要,决定着你在coding之前的设计,思路就是你的编程设计。

> + 使用webSocket来进行浏览器与服务器的实时通信

> + 服务端使用redis来缓存实时的编辑的文章,因为编辑的时候文章会出现频繁的改动,频繁的读写数据库算不上一个科学合理的解决方案

> + 服务端使用定时任务,目前设置的是每天的凌晨三点,将redis缓存的数据存储到mysql数据库中

> +  浏览器初次进入到新增文章的页面的时候,使用websocket从服务端获取数据,首先从redis中查找有没有数据,没有数据再去mysql数据库中查找

> + 浏览器初次进入到编辑页面,不需要从服务端获取数据,这样避免请求接口时间上浪费

> + 使用vue的watch方式来监听写文章页面的变化,变化时使用websocket向服务端保存到redis中

> + 文章保存的时候,清空redis和mysql的实时保存的数据


三、主要代码

const SocketIO = require('socket.io');

const config =  require('../config/environment');

const DraftRedis =  require('./draft-redis');

const redisMysql = require('./redis-mysql');

const draftPostRedisKey = config.draftPostRedisKey;

exports.initSocket = function (server) {

  console.log('init websocket');

  //socket.io

  let socketHandle = SocketIO(server, {

    serveClient: true,

    path: config.socketioPath

  });

  let draftRedis = new DraftRedis(config.db.redis);

  socketHandle.on('connection', function (socket) {

    console.log('socket connected');

    // 离开编辑文章页面

    socket.on('disconnect', function () {

      console.info('[%s] DISCONNECTED', socket.sid);

    });

    // 进入新增文章页面,获取已保存的草稿(可以为空)

    socket.on('getDraftPost', async function () {

      let data = await draftRedis.get(draftPostRedisKey);

      if (!data) {

        data = await redisMysql.getDraftPostFromMysql();

        socket.emit('getDraftPost', data);

        await draftRedis.set(draftPostRedisKey, data);

      } else {

        socket.emit('getDraftPost', data);

      }

    });

    // 实时保存文章内容

    socket.on('saveDraftPost', async function (data) {

      let res = await draftRedis.set(draftPostRedisKey, data);

      socket.emit('saveDraftPost', res);

    });

    // 保存后清空已保存的文章草稿

    socket.on('clearDraftPost', async function () {

      await draftRedis.destroy(draftPostRedisKey);

      await redisMysql.clearDraftPostOfMysql();

      socket.emit('clearDraftPost', true);

    });

  });

};


四、方法说明

+ 目前个人博客的后台使用的是,只有一个账户,没有添加多账户体系,所以redis的mysql中只存有一条记录。后续有空会慢慢加上多账户体系

+ 涉及到的模块及说明

1、/server/util/draft-socketio.js

服务端websocket服务,使用socket.io库

2、/server/util/draf-redis.js

redis的set方法和get公共方法

3、/server/util/redis-mysql.js

> redisToMysqlTask方法:定时同步redis数据到mysql数据的方法,使用node-schedule库实现定时同步

>getDraftPostFromMysql方法:redis中不存在的数据时候,从mysql中查询数据

>clearDraftPostOfMysql方法:从mysql中删除数据,文章保存后操作

4、/src/main.js

浏览器端先导入socket.io,使用vue-socket.io和socket.io-client库

import VueSocketio from 'vue-socket.io';

import socketio from 'socket.io-client';

Vue.use(VueSocketio, socketio('http://localhost:9000', {

  path: '/testsocketiopath'

}));


5、/src/pages/edit.vue

使用websocket从服务端获取数据,并实施将数据传输到服务端进行保存


五、总结

+ 整个功能本质上就是:webSocket、redis、mysql的使用,这几个之前使用过,没有联合使用过,还算是比较完满实现文章的实时保存

+ 最后欢迎[fork](https://github.com/saucxs/songEagle)和[start](https://github.com/saucxs/songEagle)


文章转载:原创
感谢你的阅读,本文由 sau交流学习社区 版权所有。
如若转载,请注明出处:sau交流学习社区-power by saucxs(程新松)(/page/523.html)
交流咨询
    官方QQ群
    群号663940201,欢迎加入!
    sau交流学习社区交流群

微信群
欢迎加入微信群
微信公众号
欢迎关注微信公众号

图文推荐

微信群
saucxs聊天机器人
saucxs
hi ,欢迎来到sau交流学习社区,欢迎与我聊天,问我问题哦!
您正在使用的浏览器是,不在支持范围内!
为了您的正常使用与展示,推荐使用Chrome浏览器68以上版本
支持浏览器:
火狐浏览器最新版
Safari浏览器最新版
Edge浏览器最新版
IE浏览器10,11