您的位置:首頁>遊戲>正文

自訂事件解決重複請求BUG

現在, 元件化開發還是比較流行的, 畢竟其優點相當突出。 最近在開發一個元件的時候, 遇到了一個很有意思的BUG。 。 。

BUG的背景

最近在開發一個元件, 好不容易開發好了轉測試。 然後, 測試給我提了一個這樣的bug, orz...

因為是一個元件, 最大的好處就是可以隨處複用, 隨處使用, 然而, 當一個頁面用了多個元件, 只有最後一個生效的時候, 這個元件就沒有什麼意義了。 。 。

BUG原因查找

這個元件的初始資料來源的介面是固定的, 也就是說, 頁面內的所有這個元件在初始化的時候都會發出同樣的請求, 這裡的請求是jsonp的方式, 所以回呼函數是綁定在window上的一個函數, 但是在頁面中window只有一個, 所以在回檔處理的時候, 要處理的元件內的相應的資料只指向最後一個元件。 所以導致多個同樣的元件在同一個頁面中, 只有最後一個元件能在取得資料之後順利渲染出來。

BUG解決思路

最主要就是要將每次請求的callback存儲起來, 這樣就可以保證callback中對元件資料的處理不是只指向最後一個。 其次, 既然是一樣的請求, 當然不希望會發出兩次以上啦, 即一個頁面發出的每一個請求都是唯一的。

BUG解決方案

想到了發佈訂閱者模式的自訂事件, 可以寫這樣的一個模組, 每次請求發出前判斷一下之前是否有相同的模組已經發出了, 如果沒有則緩存callback發出請求, 如果有相同的請求已經發出了, 那麼檢查一下這個發出的請求是否已經完成了, 如果沒有則繼續緩存callback等待, 如果請求已經發出並且已經完成則直接處理callback。 在請求第一次回來後, 發出廣播, 把之前緩存的callback都執行一次。

自訂事件詳情

定義一個模組,

裡面有n個以回呼函數命名的事件物件, 每個物件有在被初始化的時候, 定義其狀態state, 對應的callback陣列, 請求回到的資料data。 每次調用該模組, 首先檢查對應的cbName是否被初始化, 然後檢查其state。 根據state做相應的操作並改變state的值。 state的值有3中, 分別為init、loading、loaded。 即初始化、請求中、請求完成。 處於請求完成狀態時才能執行相應的回檔。 具體如下:

define('wq.getData', function (require, exports, module) { var ls = require('loadJs'); var cache = {}; cache.init = function(cb,cbName,url){ if(!cache[cbName]){ cache[cbName] = {}; cache[cbName].state = 'init'; cache[cbName].cbs = ; cache[cbName].data = ; } cache.on(cb,cbName,url); } cache.on = function(cb,cbName,url){ if(cache[cbName].state == 'loaded'){ cb(cache[cbName].data) }else if(cache[cbName].state == 'loading'){ cache[cbName].cbs.push(cb) }else if(cache[cbName].state == 'init'){ cache[cbName].cbs.push(cb); cache[cbName].state = 'loading'; cache.fetch(cb,cbName,url); } } cache.broadcast = function(cbName){ cache[cbName].cbs.forEach(function(cb){ cb(cache[cbName].data) }); } cache.checkLoaded = function(cbName){ if(cache[cbName].data[0]){ cache[cbName].state = 'loaded'; cache.broadcast(cbName); } } cache.fetch = function(cb,cbName,url){ ls.loadScript({ url: url, charset: 'utf-8', handleError:function(func, args, context,errorObj){ console.log(_errlogText + context); cache[cbName].data[0] = {}; cache.checkLoaded(cbName); } }); if(window.cbName) return; window[cbName] = function(json){ cache[cbName].data[0] = json; cache.checkLoaded(cbName); } } exports.getData = function(cb,cbName,url){ cache.init(cb,cbName,url); } })

完美解決問題, 每個回檔都不會遺漏或者被覆蓋……

擴展思路

該模組可通用於處理一個頁面內同一個請求的情況。 還可以擴展到處理一些需要2個請求以上完成才執行某個回檔的情況。 類似於Promose的情況。 這個時候可以規定, 每個data[0]裝的是固定的對應介面的資料, data[2]對應另一個, 一次類推。 不過這樣就要遍歷到每一項都為true的時候才執行回檔。

而且對應關係比較容易混亂, 再擴展就不如直接用Promise來處理了。 。 。

Next Article
喜欢就按个赞吧!!!
点击关闭提示