競態(tài)條件Race condition及如何避免的三種方案詳解
什么是競態(tài)條件?
當(dāng)你的程序依賴正確的響應(yīng)順序,但響應(yīng)的順序又無法保證時,可能會導(dǎo)致意外的結(jié)果,這就是競態(tài)條件。
舉個用戶界面的例子:

在上圖中,分別點擊科技和生活tab時,期望能夠展示對應(yīng)的數(shù)據(jù)。
我們來設(shè)想如下情況:
- 點擊科技按鈕(高亮科技按鈕)(數(shù)據(jù)2秒后返回)
- 點擊生活按鈕(高亮生活按鈕)(數(shù)據(jù)1秒后返回)
最終,展示區(qū)域會在1秒后顯示生活數(shù)據(jù),2秒后展示科技數(shù)據(jù),但此時,我們的按鈕會高亮?xí)谏钌?,但我們的展示區(qū)域顯示的卻是科技數(shù)據(jù)。也就是高亮的按鈕和展示數(shù)據(jù)不同步,這就是競態(tài)條件造成的問題。
如何避免?
方案1:每次操作完成之前,阻止新的操作
這個方案用的比較普遍,具體思路就是請求發(fā)生期間,添加一個loading遮罩層,這樣在當(dāng)前請求響應(yīng)之前,后續(xù)的操作都會被loading遮罩層避免掉,也就不會有競態(tài)問題的發(fā)生。
方案2:每次發(fā)送請求時,丟掉上一個請求的響應(yīng)
該方案的思路是,在響應(yīng)完成之前,如果用戶有新的請求,那就丟棄掉未完成的請求,其結(jié)果就是只對最新的請求進行響應(yīng),也就避免出現(xiàn)舊的請求響應(yīng)數(shù)據(jù)展示在了當(dāng)前高亮視圖下。
function getResolveWhenLast() {
let globalId = 0;
return (pro) => {
return new Promise((resolve, reject) => {
const id = ++globalId;
pro
.then((res) => {
if (id === globalId) {
resolve(res);
}
})
.catch(err => {
if (id === globalId) {
reject(err);
}
})
})
}
}
const resolveWhenLast = getResolveWhenLast()
// 使用resolveWhenLast包住你的請求,就可以解決競態(tài)問題
resolveWhenLast(api.getPosts()).then(res => {
// ...
})方案3:每次發(fā)送請求時,取消掉上一次的請求
給promise加了一層包裝,添加了cancel的能力,每次請求發(fā)出的時候,將上一次的請求取消掉,同樣達到了只最處理最新一次請求響應(yīng)的目的,也就避免了競態(tài)條件的發(fā)生。
// 給Promise添加取消請求的能力
function createImpretivePromise(pro) {
let resolve = null;
let reject = null;
const warppedPromise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
})
pro
.then((res) => {
resolve && resolve(res);
})
.catch((err) => {
reject && reject(err);
});
// 可以切斷代理
const cancel = () => {
resolve = null;
reject = null;
}
return {
promise: warppedPromise,
cancel
}
}
const getResolveWhenLast = () => {
let globalCancel = null;
return (pro) => {
const { promise, cancel } = createImperativePromise(pro);
globalCancel && globalCancel();
globalCancel = cancel;
return promise;
};
};
const resolveWhenLast = getResolveWhenLast()
// 使用resolveWhenLast包住你的請求,就可以解決競態(tài)問題
resolveWhenLast(api.getPosts()).then((res) => {
// ...
});以上就是競態(tài)條件Race condition及如何避免的三種方案詳解的詳細內(nèi)容,更多關(guān)于競態(tài)條件 Race condition的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript 中有了Object 為什么還需要 Map 呢
Map 是用于存儲鍵值的,而 JavaScript 中對象也是由鍵值對組成的,那么 Map 存在的意義是什么呢?下面文章小編就來向大家詳細介紹吧,需要的朋友可以參考下2021-09-09
JavaScript的function函數(shù)詳細介紹
這篇文章主要介紹了JavaScript的function函數(shù)詳細,而我們的JavaScript腳本語言比較特殊,相對于C語言,它的參數(shù)是不需要數(shù)據(jù)類型加持的。返回值return,我就不過多描述,他是和 C語言通的,如果沒寫他就會自動返回undefined,下面一起來看看文章內(nèi)容,需要的朋友可以參考一下2021-11-11
autojs使用intent發(fā)送郵件帶附件實現(xiàn)示例
這篇文章主要為大家介紹了autojs使用intent發(fā)送郵件帶附件實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01

