以JS開發(fā)為例詳解版本號(hào)的作用與價(jià)值
導(dǎo)讀
在項(xiàng)目開發(fā)和運(yùn)行的過程中,總是少不了各類升級(jí)。例如某個(gè)功能組件需要更高的依賴庫(kù)、數(shù)據(jù)項(xiàng)需要進(jìn)行兼容等等問題。遇到此類問題開發(fā)者需要使用版本號(hào)來解決。今天我們就來分析一下項(xiàng)目迭代過程中會(huì)遇到的各類升級(jí)問題以及如何使用版本號(hào)來解決。
通常來說升級(jí)會(huì)涉及到三個(gè)點(diǎn):
- 向下兼容
- 協(xié)商升級(jí)
- 拒絕服務(wù)
依賴升級(jí)
開發(fā)者在產(chǎn)品演進(jìn)的過程中會(huì)不斷的升級(jí)工具依賴,以 npm 版本為例。版本號(hào)通常由三部分組成: 主版本號(hào)、次版本號(hào)和修訂版本號(hào)。
Major.Minor.Patch
其中,Major 表示主版本,當(dāng)你做了不兼容的 API 修改時(shí),就需要升級(jí)這個(gè)版本號(hào)。Minor 表示次版本,當(dāng)你做了向下兼容的功能性新增時(shí),就需要升級(jí)這個(gè)版本號(hào)。而 Patch 表示修訂版本,當(dāng)你做了向下兼容的問題修正時(shí),就需要升級(jí)這個(gè)版本號(hào)。
每次在使用 npm install 時(shí)都會(huì)下載
package.json 中的依賴。而在在依賴中有 ^ 和 ~ 符號(hào)。其中 ^ 代表次版本兼容,~ 是修訂版本兼容。
{
"devDependencies": {
"lib1": "0.15.3",
"lib2": "^0.15.3",
"lib3": "~0.15.3"
}
}如果當(dāng)前三個(gè)庫(kù)都有幾個(gè)高版本,如:
- 0.15.3
- 0.15.4
- 0.16.1
- 1.0.0
在項(xiàng)目下載后執(zhí)行 install ,下載的對(duì)應(yīng)版本則是
- lib1 0.15.3
- lib2 0.16.1
- lib3 0.15.4
雖然 ^ 和 ~ 都不會(huì)升級(jí)破壞性依賴,但版本號(hào)只是“君子協(xié)議”。還是建議大家不要使用這些符號(hào)。同時(shí)之前也遇到過組件庫(kù)在某個(gè)修訂版本中出現(xiàn)了 bug。雖然很快修復(fù)好了。但是定位問題還是需要花費(fèi)一定時(shí)間的。
數(shù)據(jù)緩存
很多情況,開發(fā)者為了減少網(wǎng)絡(luò)請(qǐng)求都會(huì)使用數(shù)據(jù)緩存。如果是一個(gè)較為穩(wěn)定的數(shù)據(jù)。我們可以添加版本號(hào)進(jìn)行緩存(同時(shí)添加一個(gè)足夠長(zhǎng)的過期時(shí)間方便重新獲獲?。?/p>
以 localStorage 為例,代碼如下所示:
interface Store<T> {
/** 存儲(chǔ)數(shù)據(jù) */
data: T;
/**
* 當(dāng)前版本數(shù)據(jù),可以是一個(gè)數(shù)字或一個(gè)日期字符串 '220101-1'
* 后續(xù)的 -1 是為了當(dāng)天發(fā)布多個(gè)版本而準(zhǔn)備的。
*/
version: string | number;
/**
* 過期時(shí)間
* 可以使用 時(shí)間戳(天數(shù)),天數(shù) dayjs 等
*/
expries: string | number;
}
/**
* 實(shí)際存儲(chǔ) key 值
*/
const XXX_STORAGE_KEY = 'storageKey';
const isNeedUpgrade = async <T>(): Promise<boolean> => {
const storeJSONStr = localStorage.getItem(XXX_STORAGE_KEY);
// 沒有存儲(chǔ) JSON 字符串
if (storeJSONStr === null) {
return true;
}
let store: Partial<Store<T>> = {};
try {
store = JSON.parse(storeJSONStr)
} catch (e) {
// JSON 字符串解析失敗
return true;
}
const { expries, version: localVersion } = store;
// 沒有過期時(shí)間獲取當(dāng)前時(shí)間超過過期時(shí)間
if (!expries || isOverTime(expries)) {
return true;
}
// 沒有緩存本地版本
if (!localVersion) {
return true;
}
const currentVersion = await getCurrentVersionForXXXStore();
// 版本不一致
if (currentVersion !== localVersion) {
return true;
}
// 無需升級(jí)
return false;
}當(dāng)前代碼其實(shí)就涉及到了上述所說的協(xié)商升級(jí)。
使用版本號(hào)進(jìn)行 api 維護(hù)
隨著業(yè)務(wù)的發(fā)展,數(shù)據(jù)結(jié)構(gòu)不可避免會(huì)發(fā)生一定的改變,如果僅僅只是增加一個(gè)數(shù)據(jù),開發(fā)者可以直接在服務(wù)端做一下向下兼容即可。但有些時(shí)候我們可能需要做出一系列的調(diào)整,諸如前一個(gè)版本處理傳遞上來的 A 和 C 數(shù)據(jù),但是后一個(gè)版本需要處理 A 和 D 數(shù)據(jù)。這時(shí)候我們可能就無法通過數(shù)據(jù)傳輸來確定如何使用。因?yàn)槲覀儫o法保證服務(wù)端與客戶端能夠同步升級(jí)。
此時(shí)我們不得不借助版本號(hào)。新版本前端調(diào)用新版本的 API ,舊版本前端調(diào)用舊版本的 API。
/**
* 2019-11-12 版本 15 兼容處理了 xxxx, xxxx
* 2018-12-10 版本 14 xxxxxx
*/
const api = initRequest({
// 全局 api 版本號(hào)
apiVersion: 15,
});
const queryXXX = () => {
return api({
// 可以使用 api 版本號(hào),不傳遞默認(rèn)使用全局版本號(hào)
apiVersion: 3,
});
};使用或者不使用全局版本號(hào)都有各自的優(yōu)點(diǎn)。使用全局版本號(hào)一個(gè)版本可以同時(shí)進(jìn)行多處修改,方便開發(fā)者維護(hù)。但是如果 api 兼容過多的話,apiVersion 也會(huì)升級(jí)的很快。最終反而不利于維護(hù)。大家可以酌情處理,如果是互聯(lián)網(wǎng)項(xiàng)目,大家可以考慮使用 api 獨(dú)立版本號(hào),如果是企業(yè)服務(wù)則優(yōu)先使用全局版本號(hào)。
大部分情況下服務(wù)端都可以兼容之前的代碼。
@Controller({
path: "user",
version: "2",
})
export class UserController {
@Get()
@Version("2")
findAll() {
return this.userService.findAll();
}
@Get()
@Version("1")
findAllOld() {
return this.userService.findAllOld();
}
}極少數(shù)情況下,服務(wù)端代碼難以兼容,或者需要付出極大代價(jià),這時(shí)候就可以拒絕服務(wù)。
@Controller({
path: "user",
version: "2",
})
export class UserController {
@Get()
@Version("1")
findAllOld() {
// 拋出版本不支持異常
throw BusinessException.throwVersionNotSupport();
}
}老的前端代碼中后端拒絕服務(wù)。這樣的話就不需要在服務(wù)端維護(hù)多個(gè)版本。代碼如下所示:
export const handleVersionError(err) {
// 版本不支持和
if (err.errCode !== 'versionNotSupport') {
return;
}
this.$confirm('當(dāng)前版本過低,無法正常使用此功能。', '溫馨提示', {
confirmButtonText: '刷新頁(yè)面使用最新版本',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
location.reload();
})
}如果使用小程序開發(fā),也可以通過小程序 API updateManager 重啟升級(jí)。代碼如下所示:
const updateManager = Taro.getUpdateManager();
updateManager.onCheckForUpdate(function (res) {
// 請(qǐng)求完新版本信息的回調(diào)
console.log(res.hasUpdate);
});
updateManager.onUpdateReady(function () {
Taro.showModal({
title: "更新提示",
content: "新版本已經(jīng)準(zhǔn)備好,是否重啟應(yīng)用?",
success: function (res) {
if (res.confirm) {
// 新的版本已經(jīng)下載好,調(diào)用 applyUpdate 應(yīng)用新版本并重啟
updateManager.applyUpdate();
}
},
});
});
updateManager.onUpdateFailed(function () {
// 新的版本下載失敗
});當(dāng)然,針對(duì)小程序開發(fā)者還可以存儲(chǔ)當(dāng)前頁(yè)面和獲取信息,如果重啟小程序后,直接打開對(duì)應(yīng)界面并刪除信息(添加超時(shí)機(jī)制)。
樂觀鎖
樂觀鎖也是利用了版本號(hào)來實(shí)現(xiàn)的。
當(dāng)一些可變數(shù)據(jù)無法隔離時(shí)候,開發(fā)者可以用兩種不同的控制策略:樂觀鎖策略和悲觀鎖策略。樂觀鎖用于沖突檢測(cè),悲觀鎖用于沖突避免。
悲觀者策略非常簡(jiǎn)單,當(dāng) A 用戶獲取到用戶信息時(shí)系統(tǒng)把當(dāng)前用戶信息給鎖定,然后 B 用戶在獲取用戶信息時(shí)就會(huì)被告知?jiǎng)e人正在編輯。等到 A 員工進(jìn)行了提交,系統(tǒng)才允許 B 員工獲取數(shù)據(jù)。此時(shí) B 獲取的是 A 更新后的數(shù)據(jù)。
樂觀者策略則不對(duì)獲取進(jìn)行任何限制,它可以在用戶信息中添加版本號(hào)來告知用戶信息已被修改。樂觀鎖要求每條數(shù)據(jù)都有一個(gè)版本號(hào),同時(shí)在更新數(shù)據(jù)時(shí)候就會(huì)更新版本號(hào),如 A 員工在更新用戶信息時(shí)候提交了當(dāng)前的版本號(hào)。系統(tǒng)判斷 A 提交的時(shí)候的版本號(hào)和該條信息版本號(hào)一致,允許更新。然后系統(tǒng)就會(huì)把版本號(hào)修改為新的版本號(hào),B 員工來進(jìn)行提交時(shí)攜帶的是之前版本號(hào),此時(shí)系統(tǒng)判定失敗。
業(yè)務(wù)也可以根據(jù)情況添加用戶問詢,詢問用戶是否需要強(qiáng)制更新,在用戶選擇“是”時(shí)可以添加額外參數(shù)并攜帶之前的版本號(hào)以方便日志信息存儲(chǔ)。
當(dāng)然了,如果當(dāng)前業(yè)務(wù)對(duì)時(shí)間要求沒有那么高的情況下,開發(fā)者也可以直接利用數(shù)據(jù)的更新時(shí)間作為這條數(shù)據(jù)的版本號(hào)。
以上就是以JS開發(fā)為例詳解版本號(hào)的作用與價(jià)值的詳細(xì)內(nèi)容,更多關(guān)于JS開發(fā)版本號(hào)作用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解JavaScript中數(shù)組的相關(guān)知識(shí)
這篇文章主要介紹了JavaScript中中數(shù)組的相關(guān)知識(shí),是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-07-07
JavaScript?Canvas實(shí)現(xiàn)兼容IE的兔子發(fā)射爆破動(dòng)圖特效
這篇文章主要為大家介紹了JavaScript?Canvas實(shí)現(xiàn)兼容IE的兔子發(fā)射爆破動(dòng)圖特效示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
基于JavaScript代碼實(shí)現(xiàn)微信掃一掃下載APP
有很多人在做微信的掃一掃下載。但是在微信更新之后微信將該功能給禁止掉了,也不能說是全面禁止吧,因?yàn)轵v訊、微信是一家嘛,通過應(yīng)用寶審核的應(yīng)用好像還是可以通過掃一掃直接下載的,下面通過本篇文章給大家介紹微信掃一掃下載app的代碼片段,感興趣的朋友一起看看吧2015-12-12

