小喵的在線共享編輯器


小喵的嘮叨話:寫這篇博客的初衷是因為看到了室友電腦面試的時候,面試官要求在線寫代碼。然后就想到,如果兩個人能夠在同一個頁面進行編輯工作,不就能更方便的調試代碼了嗎?(PS.懂linux的screen或tmux的可以繞道了。)代碼十分簡單,在一個月前就寫完了,只是一直沒有時間寫博客說明一下。

 

!請不要用這個編輯特別大的文件!

!小喵的服務器很菜雞的!!!!/(ㄒoㄒ)/~~ 

 

 

原博客地址:http://www.miaoerduo.com/nodejs/小喵的在線共享編輯器.html

 

心急的同學可以在 http://www.editor.miaoerduo.com/?doc=demo 先預覽一下效果。打開頁面兩次,進行編輯工作時會發現兩邊的頁面做出了同樣的修改。

github:https://github.com/miaoerduo/shared-editor 歡迎forkstar

那么,實現一個這樣的在線的共享編輯器需要哪些工作呢?我們下面一點一點的說明。

一、寫在前面

熟悉Linux的同學都知道screen和tmux這兩個工具。通常我們可以使用他們來執行一些長時間的任務,也可以使用他們的共享終端的功能。在結對編程中,這是很有效的一個工具。

本文要實現的,是和上述兩個工具類似的共享編輯器。要說優點的話,可能就是更親民一些,打開網頁就能使用。很適合遠程幫女票看個代碼啥的(好像很多公司里面會截斷websocket,這樣就沒法用了)。

實現一個這樣的編輯器,主要有兩個部分。編輯器和同步數據的服務端。下面我們依次介紹。

二、在線編輯器

首先,我們需要一個好看的編輯器。調研了一下,找到了ACE這個編輯器,網址是 https://ace.c9.io ,簡單的了解了一下這個編輯器,發現居然連Github用的都是這個編輯器!看來我們選擇這個編輯器是沒錯的啦。

使用起來也異常的簡單,官方的Demo如下:

<!DOCTYPE html>
<html lang="en">
<head>
<title>ACE in Action</title>
<style type="text/css" media="screen">
#editor { 
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
</style>
</head>
<body>

<div id="editor">function foo(items) {
    var x = "All this is syntax highlighted";
    return x;
}</div>

<script src="/ace-builds/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/monokai");
    editor.getSession().setMode("ace/mode/javascript");
</script>
</body>
</html>

 

上面的script中的src可能需要換成可以訪問的鏈接。之后就能預覽到編輯器的效果。大致和前面小喵的效果類似。

具體的其他的用法可以在官網中查到,這里小喵就不着重介紹了。

三、消息同步機制

選擇好合適的編輯器之后,我們需要做的就是消息通信的功能了。

這里主要有四種情況:

1. 文檔同步。當用戶修改文檔的時候,其修改的部分必須同步到所有的閱讀改文檔的用戶。這里只同步修改的部分,因為每次都同步整個文檔,那么會很消耗帶寬(總不能輸入一個 "hello world"都同步十幾次文檔吧)。

下圖是一個示例(強勢安利一下:https://www.processon.com 這個畫圖的工具)。用戶1編輯了文檔,文檔更新的內容發送給了服務器,服務器將更新的內容組播到所有打開相同文檔的用戶(注意,這里不是廣播,廣播是向所有的用戶發送),同時更新自己的遠程備份。

圖1 文檔更新

2. 文檔副本。當用戶第一次訪問已經存在的文檔的時候。這個時候,該用戶需要加載頁面的所有的內容。因此我們的服務器端需要存放完整的文檔的副本。

如下圖,用戶3打開了這個文檔,這時候會請求服務器發送完整的文檔信息。

圖2 新增用戶

3. 文檔銷毀。小喵這里的文檔的內容是直接在內存中保存的。這樣的好處是很方便,不需要額外的控制數據庫啥的。但是弊端也很明顯,雖然每個文檔可能比較小,但如果文檔創建的比較多,就會一直消耗內存。所以當沒有用戶使用文檔的時候,需要刪除文檔,這樣服務器端就需要保存一個引用計數。計數為0,就刪除文檔。

4. 沖突解決。考慮到網絡可能會出現故障,用戶在編輯文檔之后,其他的用戶可能並沒有即使同步,這樣就出現文檔落后的情況。一個簡單的策略就是,每次文檔修改之后都返回一個時間戳,下一次修改文檔的時候要將這個時間戳作為參數發送到服務器,如果時間戳不是最新的,那么就刷新整個文檔。當然這個策略也有很多的不足之處,如果大家能有什么改進,煩請告訴小喵一下~

上面就是設計部分,具體實現的話,需要用到WebSocket技術,這是瀏覽器和服務器實時通信的一個很好的工具。WebSocket有很多語言的實現,小喵這里選擇的是比較容易上手的socket.io

socket.io 不僅支持用戶和服務器的點對點通信,還支持組播、廣播的操作。簡單的學習一下,就可以完成上面的設計。

這里,小喵也不在代碼層面上解釋實現了。感興趣的同學可以看看小喵的github: https://github.com/miaoerduo/shared-editor 能夠給小喵提交一些PR的話就更好了。

四、寫在后面

終於寫完這篇博客了,拖了快兩個月了。之前遲遲沒有動手的一個原因是比較忙,更多的可能因為自己有點懶,一直不想畫解釋原理的示意圖。現在終於寫完了,還是挺開心的。

這次的博客相比之前的,更多的是介紹設計的思路。反正代碼都在github上了,大家可以隨意食用~

希望能和大家一起進步!

 

轉載請注明出處,謝謝~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM