dojo.DeferredList

<本文譯自http://dojotoolkit.org/reference-guide/dojo/DeferredList.html#dojo-deferredlist>

dojo.Deferred提供了一種“一問一答”的事件處理機制,dojo.DeferredList則在其之上提供了“一個答案回答多個問題”的機制。<譯註:“一個答案回答多個問題”更符合publisher-subscriber模型。dojo.DeferredList處理的是一個事件必須以多個事件的完成爲前提的情況,即Windows API WaitForMultipleObjects應用的場合。>

一個常見的任務是,當一串由不同服務提供的資源都可用時,通知某個阻塞的任務開始執行。例如,一個跨多個書店的搜索操作。

<譯註:此處省略關於爲什麼需要DeferredList的若干說明。大意是,以一個跨多個書店的搜索操作爲例,用戶需要看到的時所有書店的搜索結果的綜合結果。一種不好的做法是,依次發出對每個書店的搜索請求,蒐集結果,在所有搜索請求完成之後再綜合結果。這樣整個操作串行化了,耗時爲每個操作耗時的總和;如果使用DeferredList,則耗時爲單個操作的最長時間。其實使用DeferredList還有另一個好處,就是代碼形式上的簡潔>

代碼示例:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr">
    
    <head>
        <style type="text/css">
            body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
        </style>
        <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
        </script>
        <script type="text/javascript">
            dojo.require("dojo.DeferredList");
            dojo.require("dijit.form.Button");
            dojo.addOnLoad(function() {

                // stub search functions to simulate network delay
                function searchAmazon() {
                    var d = new dojo.Deferred();
                    setTimeout(function() {
                        d.callback("We found books at amazon");
                    },
                    500);
                    return d;
                }

                function searchBol() {
                    var d = new dojo.Deferred();
                    setTimeout(function() {
                        d.callback("We found books at bol");
                    },
                    700);
                    return d;
                }

                function searchGoogle() {
                    var d = new dojo.Deferred();
                    setTimeout(function() {
                        d.callback("We found books at google");
                    },
                    200);
                    return d;
                }

                dojo.connect(dijit.byId("search"), "onClick", function() {
                    var d1 = searchAmazon(),
                    d2 = searchBol(),
                    d3 = searchGoogle();

                    dojo.byId("statusSearch").innerHTML = "Searching....";

                    // create a deferred list to aggregate the state
                    var dl = new dojo.DeferredList([d1, d2, d3]);

                    // a DeferredList has much the same API as a Deferred
                    dl.addCallback(function(res) {
                        // "res" is an array of results
                        dojo.byId("statusSearch").innerHTML = "Result: " + res[0][1] + ", " + res[1][1] + ", " + res[2][1];
                        console.log(res);
                    });
                });
            });
        </script>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dijit/themes/claro/claro.css"
        />
    </head>
    
    <body class=" claro ">
        <button dojoType="dijit.form.Button" id="search">
            Search
        </button>
        <div style="margin: 10px;">
            Status:
            <span id="statusSearch">
            </span>
        </div>
        <!-- NOTE: the following script tag is not intended for usage in real
        world!! it is part of the CodeGlass and you should just remove it when
        you use the code -->
        <script type="text/javascript">
            dojo.addOnLoad(function() {
                if (document.pub) {
                    document.pub();
                }
            });
        </script>
    </body>

</html>

<譯註:代碼searchXXX使用setTimeout對異步操作進行了模擬,真實的代碼更象是下面這樣:

function searchAmazon(query){
  return dojo.xhr("GET", {
    url: "/books/amazon",
    content: { q: query }
  });
}
dojo.xhr會返回一個Deferred對象,也就是說,在其內部實現裏,會有一個deferred.callback({/*some result object*/})的調用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章