js異步狀態監控

說明:寫這篇文章,是但願被吐槽的。ajax

1、背景promise

在作報表頁面的時候,頁面上有不少的異步加載,而設計的loading是個全局的,一個頁面就有一個。異步

控制loading何時出現,何時消失,要實時的知道頁面上異步加載的東西是否執行完畢,只有全部的異步都加載完,loading才能中止。ide

而且,若是用戶操做了頁面,某個局部又要開始加載,loading要被通知到,執行loading效果。函數

問題的難點有兩個:this

1.怎麼知道全部的異步都加載完閉了呢?spa

2.如何通知loading?prototype

2、思路設計

1.思路一code

設計一個外部狀態map,異步執行完畢,就修改外部變量的值。開一個計時器,不斷的這個map,若是所有加載完畢,就中止loading。

// 狀態集合
  var statusMap = {
      "異步1": false,
      "異步2": false
      // ...
  };
  
 // 計時器不斷檢查狀態
 setInterval(function () {
     // 檢查statusMap
     if (isReady(statusMap)) {
         // show loading
     } else {
         // hide loading
     }
 }, 1000);
 
 //異步
 $.ajax({
     //...
     success: function () {
         statusMap["異步1"] = true;
     }
 });

 

這個方案雖然能解決問題,可是太不夠優雅,呵呵呵呵......

2.思路二

使用promise或者jQuery的deferred(@上位者的憐憫 提供的建議)。

$.when(異步1,異步2).done(function(){
    // show loading
}).fail(function(){
    // hide loading
});

 

這個方案有個弊端,一旦異步加載完畢,不能修改promise的狀態了,所以不適合這個場景。

3.思路三

本身造輪子基於事件監聽的,一個狀態改變,就掃一遍全部監聽的對象,最後再根據用狀態,回調對應的函數

3、思路三實現

 

(function (win) {
    var watch = function () {
        var that = this;
        // arr
        if (arguments.length == 1 && Object.prototype.toString.call(arguments[0]) === "[object Array]") {
            that.watchArr = arguments[0];
        } else {
            that.watchArr = Array.prototype.slice.call(arguments);
        }
        that.watchArr.forEach(function (fairy) {
            fairy.watch = that;
        });
        that.isReady = true;
        return that;
    };
    watch.prototype = {
        ready: function (callback) {
            this.readyHandler = callback;
            this.check();
            return this;
        },
        unready: function (callback) {
            this.unReadyHandler = callback;
            this.check();
            return this;
        },
        add: function (fairy, check) {
            this.watchArr.push(fairy);
            if (check === undefined || check === true) {
                this.check();
            }
            return this;
        },
        check: function () {
            var nowIsReady = this.watchArr.every(function (fairy) {
                return fairy.isReady;
            });
            if (nowIsReady != this.isReady) {
                if (nowIsReady) {
                    if (this.readyHandler) {
                        this.readyHandler.call();
                        this.isReady = true;
                    }
                } else {
                    if (this.unReadyHandler) {
                        this.unReadyHandler.call();
                        this.isReady = false;
                    }
                }
            }
        },
        setIsReadyById: function (id, isReady, check) {
            var index = this.watchArr.indexOf(function (fairy) {
                fairy.id = id;
            });
            this.watchArr[index].isReady = isReady;
            if (check === undefined || check === true) {
                this.check();
            }
        },
        setIsReadyAll: function (isReady, check) {
            this.watchArr.forEach(function (fairy) {
                fairy.isReady = isReady;
            });
            if (check === undefined || check === true) {
                this.check();
            }
        }
    };

    var fairy = function (isReady) {
        this.id = new Date().getTime();
        this.isReady = isReady || false;
    };
    fairy.prototype = {
        toReady: function () {
            this.isReady = true;
            this.watch.check();
        },
        toUnReady: function () {
            this.isReady = false;
            this.watch.check();
        }
    };

    win.Watch = watch;
    win.Fairy = fairy;
})(window);

 

// 用例
var loader = new Loader();
var listFairy = new Fairy();
var chartFairy = new Fairy();
var watch = new Watch(listFairy, chartFairy);
watch.ready(function () {
    loader.stop();
}).unready(function () {
    loader.start();
});

//異步
$.ajax({
    //...
    success: function () {
        listFairy.toReady();
    }
});

 

納尼,說好的事件呢,哪裏去了。

好吧,吐槽點來了,實現的過程當中,發現其實不必用事件。

實現到最後,發現它其實就是一個變相的思路一。

the end 未完不續 ...

相關文章
相關標籤/搜索