習(xí)筆記60:異步任務(wù)取消與重復(fù)提交防護(hù))
個(gè)人主頁(yè)楊利杰YJlio??個(gè)人專欄《Windows 疑難雜癥與工單復(fù)盤案例庫(kù)》 《Sysinternals實(shí)戰(zhàn)教程》《WINDOWS教程》 《Windows PowerShell 實(shí)戰(zhàn)》 《IOS插件分析測(cè)試》《超簡(jiǎn)單用Python讓Excel飛起來(lái)》讓復(fù)雜的事情更簡(jiǎn)單讓重復(fù)的工作自動(dòng)化HarmonyOS 7.0學(xué)習(xí)筆記60異步任務(wù)取消與重復(fù)提交防護(hù)文章目錄HarmonyOS 7.0學(xué)習(xí)筆記60異步任務(wù)取消與重復(fù)提交防護(hù)一、先給任務(wù)狀態(tài)劃清邊界二、重復(fù)提交要在入口處攔住三、取消動(dòng)作不一定等于任務(wù)已經(jīng)停止四、讓只有當(dāng)前任務(wù)更新頁(yè)面五、區(qū)分當(dāng)前請(qǐng)求和過期響應(yīng)六、重試應(yīng)由明確規(guī)則觸發(fā)七、用場(chǎng)景矩陣覆蓋邊界八、這篇練習(xí)的檢查清單參考資料大家好我是楊利杰 YJlio。異步操作開始后界面要面對(duì)幾個(gè)很實(shí)際的問題用戶連續(xù)點(diǎn)了幾次、任務(wù)進(jìn)行中想取消、舊請(qǐng)求晚于新請(qǐng)求返回以及失敗后是否允許重試。如果這些邊界沒有提前約定頁(yè)面可能出現(xiàn)重復(fù)任務(wù)、舊結(jié)果覆蓋新結(jié)果或“看起來(lái)取消了但仍在更新”的情況。這篇我把關(guān)注點(diǎn)放在請(qǐng)求中狀態(tài)、重復(fù)操作攔截和結(jié)果收斂上。原稿沒有提供具體異步 API、取消接口或運(yùn)行記錄因此本文以狀態(tài)設(shè)計(jì)和驗(yàn)證方法為主不將示意圖寫成已經(jīng)實(shí)現(xiàn)的功能。一、先給任務(wù)狀態(tài)劃清邊界我會(huì)先把一次操作抽象為幾種互斥狀態(tài)尚未開始、正在執(zhí)行、成功、失敗、已取消。成功、失敗和取消是不同的結(jié)束原因頁(yè)面提示和后續(xù)行為也不應(yīng)混成一個(gè)“完成”。在開始實(shí)現(xiàn)前可以先回答任務(wù)運(yùn)行時(shí)觸發(fā)按鈕顯示什么狀態(tài)取消動(dòng)作是中止底層操作還是只讓當(dāng)前頁(yè)面不再接收它的結(jié)果失敗后用戶能否主動(dòng)重試任務(wù)成功后重復(fù)操作是否仍然允許這些選擇要跟業(yè)務(wù)目的對(duì)應(yīng)。對(duì)讀取類請(qǐng)求和會(huì)產(chǎn)生副作用的提交操作重復(fù)執(zhí)行帶來(lái)的影響并不一樣。二、重復(fù)提交要在入口處攔住最直觀的防護(hù)是在任務(wù)進(jìn)行期間阻止同一入口再次啟動(dòng)例如暫時(shí)禁用觸發(fā)控件或在調(diào)用邊界檢查是否已有任務(wù)。具體采用哪種方式應(yīng)由項(xiàng)目現(xiàn)有狀態(tài)管理和異步實(shí)現(xiàn)決定。這里要區(qū)分界面防抖和業(yè)務(wù)冪等。按鈕禁用可以減少用戶重復(fù)操作但網(wǎng)絡(luò)重試、頁(yè)面重建或客戶端重發(fā)仍可能造成服務(wù)端重復(fù)處理。若一次操作有寫入、扣費(fèi)或創(chuàng)建記錄等副作用還需要服務(wù)端或業(yè)務(wù)層的冪等設(shè)計(jì)僅靠界面狀態(tài)不能保證請(qǐng)求只執(zhí)行一次。三、取消動(dòng)作不一定等于任務(wù)已經(jīng)停止“用戶點(diǎn)了取消”首先表示界面收到了取消意圖但底層操作是否真的停止要看具體 API 和服務(wù)能力。有些調(diào)用支持中止有些調(diào)用無(wú)法撤回只能讓頁(yè)面忽略遲到的結(jié)果。因此我會(huì)分別核驗(yàn)兩件事執(zhí)行層當(dāng)前工程使用的異步調(diào)用是否支持真正取消取消后底層任務(wù)是否停止展示層即使底層不能中止舊結(jié)果是否會(huì)被頁(yè)面識(shí)別為過期并丟棄未經(jīng)接口文檔和運(yùn)行觀察不能把第二種“忽略結(jié)果”說成第一種“取消了網(wǎng)絡(luò)請(qǐng)求”。這兩個(gè)詞對(duì)應(yīng)的行為不同。四、讓只有當(dāng)前任務(wù)更新頁(yè)面多個(gè)操作可能先后開始、按相反順序返回。為避免舊結(jié)果覆蓋新狀態(tài)結(jié)果更新時(shí)需要確認(rèn)它仍屬于當(dāng)前有效任務(wù)。實(shí)現(xiàn)上可以依據(jù)工程支持的任務(wù)標(biāo)識(shí)或狀態(tài)機(jī)制來(lái)判斷本文不指定未經(jīng)核驗(yàn)的 ArkTS API。如果結(jié)果已經(jīng)過期就不應(yīng)繼續(xù)改寫當(dāng)前輸入對(duì)應(yīng)的頁(yè)面狀態(tài)。與此同時(shí)結(jié)束清理也要謹(jǐn)慎前一個(gè)任務(wù)結(jié)束時(shí)不能誤把后一個(gè)仍在運(yùn)行的任務(wù)標(biāo)成空閑。任務(wù)歸屬檢查和加載狀態(tài)清理應(yīng)該圍繞同一個(gè)“當(dāng)前任務(wù)”規(guī)則設(shè)計(jì)。五、區(qū)分當(dāng)前請(qǐng)求和過期響應(yīng)排查異步問題時(shí)我會(huì)為每次操作記錄足以區(qū)分先后的信息例如本地任務(wù)序號(hào)、觸發(fā)時(shí)間或輸入摘要是否記錄原文要服從隱私規(guī)則。重點(diǎn)不是采用某一種標(biāo)識(shí)方案而是讓日志能回答“這條結(jié)果對(duì)應(yīng)哪次操作”。適合在練習(xí)記錄中核對(duì)的時(shí)間線包括先啟動(dòng)任務(wù) A再啟動(dòng)任務(wù) BB 先返回A 后返回。此時(shí)需要觀察最終頁(yè)面是否仍呈現(xiàn) B 的當(dāng)前結(jié)果。若只有單次請(qǐng)求測(cè)試很難發(fā)現(xiàn)順序變化帶來(lái)的覆蓋問題。六、重試應(yīng)由明確規(guī)則觸發(fā)失敗后是否重試取決于失敗原因、業(yè)務(wù)副作用和服務(wù)端約定。用戶主動(dòng)重試、應(yīng)用自動(dòng)重試、用戶取消后再次發(fā)起是不同操作不能把它們都當(dāng)成一次重復(fù)點(diǎn)擊。我會(huì)先確認(rèn)失敗是否可能已經(jīng)在服務(wù)端產(chǎn)生結(jié)果重試會(huì)不會(huì)重復(fù)創(chuàng)建或計(jì)費(fèi)取消后是否保留輸入再次發(fā)起是否創(chuàng)建新的任務(wù)上下文。若這些問題尚未核對(duì)就不應(yīng)該添加自動(dòng)重試邏輯。七、用場(chǎng)景矩陣覆蓋邊界與其只測(cè)試一次成功我更愿意把操作順序?qū)懗尚【仃囍饤l觀察按鈕狀態(tài)、任務(wù)數(shù)量和最終展示場(chǎng)景需要觀察的結(jié)果單次觸發(fā)是否進(jìn)入處理中最終狀態(tài)是否符合實(shí)際返回快速連續(xù)點(diǎn)擊是否被入口攔截是否意外啟動(dòng)多個(gè)任務(wù)成功后再次提交是否按業(yè)務(wù)要求允許新任務(wù)失敗后重試是否由明確動(dòng)作觸發(fā)是否產(chǎn)生重復(fù)副作用運(yùn)行中取消底層操作是否真正停止頁(yè)面是否停止接受結(jié)果舊任務(wù)遲到是否覆蓋了新任務(wù)的狀態(tài)或結(jié)果離開頁(yè)面再返回頁(yè)面狀態(tài)和任務(wù)生命周期是否符合預(yù)期測(cè)試時(shí)我會(huì)保留完整操作順序和環(huán)境信息。如果實(shí)際工程沒有對(duì)應(yīng)的取消能力或運(yùn)行日志就把未驗(yàn)證項(xiàng)明確列出而不是根據(jù)界面按鈕推測(cè)底層行為。八、這篇練習(xí)的檢查清單準(zhǔn)備在工程中實(shí)現(xiàn)時(shí)我會(huì)檢查任務(wù)狀態(tài)是否互斥且有明確轉(zhuǎn)換條件運(yùn)行中的重復(fù)操作是否在正確邊界被攔截取消語(yǔ)義是否與底層 API 能力一致遲到結(jié)果和過期任務(wù)是否不能覆蓋當(dāng)前頁(yè)面失敗重試是否由業(yè)務(wù)規(guī)則允許并考慮重復(fù)副作用關(guān)鍵路徑是否在目標(biāo) SDK/API 與設(shè)備上實(shí)際核驗(yàn)。原稿中的describeResult示例只負(fù)責(zé)本地字符串判斷和展示不包含異步任務(wù)、取消或防重復(fù)邏輯functiondescribeResult(input:string):string{returninput.trim().length0?暫無(wú)內(nèi)容:已讀取${input}}// 在頁(yè)面事件中調(diào)用并顯示返回結(jié)果觀察輸入與頁(yè)面輸出是否一致。這篇內(nèi)容說明的是需要實(shí)現(xiàn)和測(cè)試的邊界不能據(jù)此聲稱項(xiàng)目已經(jīng)具備這些保護(hù)。參考資料《HarmonyOS 7.0學(xué)習(xí)筆記異步任務(wù)取消與重復(fù)提交防護(hù)》原始學(xué)習(xí)筆記。原稿代碼僅為本地字符串展示示例。HarmonyOS 官方開發(fā)文檔華為開發(fā)者聯(lián)盟文檔中心。取消能力、異步 API 和狀態(tài)管理寫法需按工程當(dāng)前版本核對(duì)。說明本文圖片均為概念示意不是 DevEco Studio、模擬器或真機(jī)實(shí)測(cè)截圖。原稿沒有提供異步取消或重復(fù)提交保護(hù)的實(shí)現(xiàn)與實(shí)測(cè)記錄發(fā)布前請(qǐng)用實(shí)際工程驗(yàn)證并補(bǔ)充證據(jù)。返回頂部