songEagle開發系列:如何讓文章實時保存的問題

1、寫在前面

如何實現文章的實時保存?通常寫文章的寫博客的網站都會有這個功能點,這樣保證了用戶在不當心退出的狀況下數據的保存下來,這樣的交互比較符合用戶的使用心理學。對於用戶來講這是一個很是實用的功能,做爲一個博客來講,有這個仍是不錯的。哈哈^_^vue

2、實現的思路

一個功能的實現,你的編程思路很重要,決定着你在coding以前的設計,思路就是你的編程設計。node

  • 使用webSocket來進行瀏覽器與服務器的實時通訊
  • 服務端使用redis來緩存實時的編輯的文章,由於編輯的時候文章會出現頻繁的改動,頻繁的讀寫數據庫算不上一個科學合理的解決方案
  • 服務端使用定時任務,目前設置的是天天的凌晨三點,將redis緩存的數據存儲到mysql數據庫中
  • 瀏覽器初次進入到新增文章的頁面的時候,使用websocket從服務端獲取數據,首先從redis中查找有沒有數據,沒有數據再去mysql數據庫中查找
  • 瀏覽器初次進入到編輯頁面,不須要從服務端獲取數據,這樣避免請求接口時間上浪費
  • 使用vue的watch方式來監聽寫文章頁面的變化,變化時使用websocket向服務端保存到redis中
  • 文章保存的時候,清空redis和mysql的實時保存的數據

3、主要代碼

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);
    });
  });
};

複製代碼

4、方法說明

  • 目前我的博客的後臺使用的是,只有一個帳戶,沒有添加多帳戶體系,因此redis的mysql中只存有一條記錄。後續有空會慢慢加上多帳戶體系
  • 涉及到的模塊及說明 一、/server/util/draft-socketio.js 服務端websocket服務,使用socket.io庫 二、/server/util/draf-redis.js redis的set方法和get公共方法 三、/server/util/redis-mysql.js

redisToMysqlTask方法:定時同步redis數據到mysql數據的方法,使用node-schedule庫實現定時同步 getDraftPostFromMysql方法:redis中不存在的數據時候,從mysql中查詢數據 clearDraftPostOfMysql方法:從mysql中刪除數據,文章保存後操做 四、/src/main.js 瀏覽器端先導入socket.io,使用vue-socket.io和socket.io-client庫mysql

import VueSocketio from 'vue-socket.io';
import socketio from 'socket.io-client';

Vue.use(VueSocketio, socketio('http://localhost:9000', {
  path: '/testsocketiopath'
}));

複製代碼

五、/src/pages/edit.vue 使用websocket從服務端獲取數據,並實施將數據傳輸到服務端進行保存git

5、總結

  • 整個功能本質上就是:webSocket、redis、mysql的使用,這幾個以前使用過,沒有聯合使用過,還算是比較完滿實現文章的實時保存
  • 最後歡迎forkstart
相關文章
相關標籤/搜索