利用 Promise 進行驗證的一些實踐
一、業務場景
眾所周知,在客戶端中,表單是一個相當重要的內容。隨著技術的發展,在提交表單資料的時候,某些表單驗證環節會放在前端進行。因此,我們無可避免的要寫一堆 if 來處理,同時大多數的時候,如果需要提醒某些錯誤資訊時,需要加入 else 以及 else if 來控制,當然也可以使用 retrun。不過隨著表單越來越複雜,表單項之間的關聯越來越複雜的時候,看著一屏都放不下的判斷巢狀,心中是萬千草泥馬奔騰而過。
二、與 promise 的結合
promise 的出現主要是為了解決複雜的回撥巢狀,因此在這裡也是借用了這個特點,解決我們的痛點。程式碼見下:
function validate (scb = () => {}, ecb= () => {}) { return new Promise((resolve, reject) => { // area 1 if (...) reject('error message 1'); if (...) reject('error message 2'); if (...) reject('error message 3'); if (...) reject('error message 4'); ... // area 2 resolve(); }).then((result) => { // area 3 scb(); }).catch((err) => { // area 4 console.error(err); yourToastFunc(err); ecb(); }); }
程式碼中 area 1 是主要的邏輯判斷區, area 2 執行時表示 area 1 中的驗證全通過, area 3 則是全通過之後的成功回撥函式(scb => successCallback 縮寫, ecb 同),相反 area 4 是未通過之後的處理區域。這段主要是利用 reject 阻斷後續程式碼執行的特性,直接捕獲當前錯誤的地方從而確定是何條件未通過以及對應的提示語,從而提高後續的定位速度。
三、一些思考
這段程式碼本身並沒有改變多少思考正規化,本身也依賴 area 1 中的邏輯判斷語句的編寫,優點是在條件判斷的下一步做了一點統合,不必再每一個分支內重複地寫 return or toast。簡單而言,就是用 reject 儘可能代替了 else。
同時,因為 area 1 中的需要編寫判斷的原因,這裡也是耦合度較高的地方,從這方面講,是可以後續改進的地方。不過,需要掌握好平衡。
當然,後續升級的方向也可以是像 element-ui 的 form 那樣,傳入物件,傳入自定義的驗證器等等,同時這裡又要考慮作用域(用於某些表單聯動時上下文中的變數獲取)等等問題。
總之,沒有完美的解決方案。事物的發展是螺旋式前進的,實事求是,根據不同的實際抽象出不同的核心需求,然後選擇才能總結除相應的最合理的解決辦法。