讓刪除確認通吃confirm及jQuery.Deferred

最近在寫的元件有個「彈出對話框經使用者確認再刪除」的需求,原本是小事一椿,但之前介紹過使用自訂確認對話框取代window.confirm的技巧已廣泛應用在專案裡,某些時候也可能只用window.confirm就打發,問題就變複雜了。

二者最大的差異是前者($.kendoConfirm)為非同步執行,刪除動作需放在jQuery Deferred.promise()的done()方法;window.confirm則為內建同步指令,瀏覽器會等待使用者回應才往下執行,故用 if 判斷 true/false 決定是否刪除即可。

以下程式可看出兩種做法的差異:線上展示 (關於 $.kendoConfirm 的說明請參考舊文

    $(function() {
      function deleteConfirm_Kendo() {
        return $.kendoConfirm("刪除確認", "是否確定要刪除?");
      }
      function deleteConfirm_Native() {
        return confirm("是否確定要刪除?");
      }
      
      $("#btnTest1").click(function() {
        deleteConfirm_Kendo().done(function() {
          alert("刪除");
        });
      });
      $("#btnTest2").click(function() {
        if (deleteConfirm_Native()) {
          alert("刪除");
        }
      });
    });

要讓元件好用,最理想的做法是大小通吃:若確認函式傳回true/false就用 if 同步執行;若傳回jQuery Promise就用.done()非同步執行。

例如:線上展示

    $(function() {
      function deleteConfirm_Kendo() {
        return $.kendoConfirm("刪除確認", "是否確定要刪除?");
      }
      function deleteConfirm_Native() {
        return confirm("是否確定要刪除?");
      }
      function execDeleteAction() {
        alert("刪除");
      }
      function doDelete(deleteConfirm) {
        var res = deleteConfirm();
        //若函式傳回Promise, 放入done()中執行
        if (res && res.hasOwnProperty("done")) 
          res.done(execDeleteAction);
        //若函式傳回boolean,由傳回結果決定resolve或reject
        else if (res) 
          execDeleteAction();
      }
      $("#btnTest1").click(function() {
        doDelete(deleteConfirm_Kendo);
      });
      $("#btnTest2").click(function() {
        doDelete(deleteConfirm_Native);
      });
    });

以上寫法有個小缺點,執行刪除的部分必須抽出來變成函式,分於兩處呼叫。

針對這個缺點,額外加個jQuery.Deferred串場就能克服:線上展示

      function doDelete(deleteConfirm) {
        var dfd = jQuery.Deferred();
        var promise = dfd.promise();
        var res = deleteConfirm();
        //若函式傳回Promise, 替換原有Promise
        if (res && res.hasOwnProperty("done")) 
          promise = res;
        //若函式傳回boolean,由傳回結果決定resolve或reject
        else if (res) 
          dfd.resolve();
        else 
          dfd.reject();
        promise.done(function() {
          alert("刪除")
        });
      }

兩種做法都能讓刪除確認程序通吃window.confirm及jQuery.Deferred,擇一而用即可,以上提供大家參考。

歡迎推文分享:
Published 18 June 2015 12:06 AM 由 Jeffrey
Filed under: ,
Views: 7,587



意見

# Ammon said on 17 June, 2015 12:29 PM

何不直接在 deleteConfirm_Native 回傳 deferred 物件? 可以省下if判斷

# Jeffrey said on 17 June, 2015 05:01 PM

to Ammon, 在我的案例中,deleteConfirm_Native相當於呼叫端提供的Callback參數,對於從來沒學過jQuery Deferred的開發者,Callback函式只需return true或false,降低元件使用的門檻。

# Peter Tsai said on 17 June, 2015 09:12 PM

最後一個例子的 promise 物件會被 res 蓋掉而變成另一個函示回傳的 promise 物件,這兩個 promise 畢竟是在執行時期才進行判斷,反而增加程式複雜度,提升了使用者偵錯的門檻。為了省下一個 function 而改用 defer 技巧我是覺得有點 over design 了。 :p

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<June 2015>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication