共计 2437 个字符,预计需要花费 7 分钟才能阅读完成。
一、写在前面
如何实现文章的实时保存?一般写文章的写博客的网站都会有这个功能点,这样保证了用户在不小心退出的情况下数据的保存下来,这样的交互比较符合用户的使用心理学。对于用户来说这是一个非常实用的功能,作为一个博客来说,有这个还是不错的。哈哈 ^_^
二、实现的思路
一个功能的实现,你的编程思路很重要,决定着你在 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 和 start
正文完
发表至: javascript
2019-05-23