2009-08-10 146 views
1

我有一個大型應用程序需要確保在調用其他依賴於所述加載項目的例程之前加載各種項目(在不同的時間,而不僅僅是在啓動時)。我覺得有問題是我的架構是如何結束了尋找支持這一點:它要麼回調遍野,或預先與數十家整潔的小as3加載體系結構

private function SaveUser_complete(params:ReturnType):void 
{ 
     continueOnWithTheRoutineIWasIn(); 
} 

等人口密集(和嵌套回調!)。目前代碼庫只有2500行,但它將增長到大概10k左右。我只是看不到任何其他方式,但它似乎是錯誤的(和辛苦)。另外,我研究過pureMVC和Cairngorm,除了另一層抽象外,這些方法看起來同樣乏味。有什麼建議麼?

回答

1

好吧,異步操作總是會對代碼庫產生這種影響,不幸的是,你並不能做很多事情。如果您的加載操作形成某種「服務」,那麼最好製作一個IService接口,以及適當的MVC Style架構並使用數據令牌。簡述:

//In your command or whatever 
var service:IService = model.getService(); 
var asyncToken:Token = service.someAsyncOperation(commandParams); 
//some messaging is used here, 'sendMessage' would be 'sendNotification' in PureMVC 
var autoCallBack:Function = function(event:TokenEvent):void 
{ 
    sendMessage(workOutMessageNameHere(commandParams), event.token.getResult()); 
    //tidy up listeners and dispose token here 
} 
asyncToken.addEventListener(TokenEvent.RESULT, autoCallBack, false, 0, true); 

我在哪裏寫的字「workOutMessageNameHere()」我認爲是要自動的一部分,你既可以有某種巨大的開關,或地圖commandParams(網址或其他)的到消息名稱,無論哪種方式最好得到一個模型此信息(在相同的命令):

private function workOutMessageNameHere(commandParams):String 
{ 
    var model:CallbackModel = frameworkMethodOfRetrivingModels(); 
    return model.getMessageNameForAsyncCommand(commandParams); 
} 

這樣應該可以只留給你調用命令「callService」或不過你觸發它,你可以配置代碼中的回調映射/切換或可能通過解析的XML。 希望這能讓你開始,正如我剛剛意識到的,是相關的?你好,只是又一次通讀了你正在試圖解決的問題,我想你正在描述一系列有限狀態,即一個狀態機。 似乎你的序列大致是FunctionState - > LoadingState - > ResultState。這可能是更好的一般方法來管理小異步'鏈'的負載。

0

同意enzuguri。不管怎樣,你都需要大量的回調函數,但是如果你可以爲它們定義一個單一的接口,並將代碼推送到控制器類或服務管理器中,並將它們集中到一個地方,那麼它就不會變得不堪重負。

0

我知道你正在經歷什麼。不幸的是,我從未見過一個好的解決方案基本上,異步代碼只是以這種方式結束。

一個解決方案算法:

static var resourcesNeededAreLoaded:Boolean = false; 
static var shouldDoItOnLoad:Boolean = false; 

function doSomething() 
{ 
    if(resourcesNeededAreLoaded) 
    { 
     actuallyDoIt(); 
    } 
    else 
    { 
     shouldDoItOnLoad = true; 
     loadNeededResource(); 
    } 
} 

function loadNeededResource() 
{ 
    startLoadOfResource(callBackWhenResourceLoaded); 
} 

function callBackWhenResourceLoaded() 
{ 
    resourcesNeededAreLoaded = true; 
    if(shouldDoItOnLoad) 
    { 
     doSomething(); 
    } 
} 

這種模式允許你做延遲加載,但你也可以在必要時強制負荷。這種普遍的模式可以被抽象出來,並且趨向於正常工作。注意:一個重要的部分是從加載回調調用doSomething(),而不是actuallyDoIt(),原因很明顯,如果您不希望代碼不同步。

你如何抽象上述模式取決於你的具體用例。您可以擁有一個管理所有資源加載和獲取的類,並使用映射來管理加載和不加載的內容,並允許調用者在資源不可用時設置回調。例如

public class ResourceManager 
{ 
    private var isResourceLoaded:Object = {}; 
    private var callbackOnLoad:Object = {}; 
    private var resources:Object = {}; 

    public function getResource(resourceId:String, callBack:Function):void 
    { 
     if(isResourceLoaded[resourceId]) 
     { 
      callback(resources[resourceId]); 
     } 
     else 
     { 
      callbackOnLoad[resourceId] = callBack; 
      loadResource(resourceId); 
     } 
    } 

    // ... snip the rest since you can work it out ... 
} 

我可能會使用事件而不是回調,但這取決於你。有時,管理所有資源的中央類不可能,在這種情況下,您可能希望將加載代理傳遞給能夠管理算法的對象。

public class NeedsToLoad 
{ 
    public var asyncLoader:AsyncLoaderClass; 

    public function doSomething():void 
    { 
     asyncLoader.execute(resourceId, actuallyDoIt); 
    } 

    public function actuallyDoIt():void { } 
} 

public class AsyncLoaderClass 
{ 
    /* vars like original algorithm */ 

    public function execute(resourceId:String, callback:Function):void 
    { 
     if(isResourceLoaded) 
     { 
      callback(); 
     } 
     else 
     { 
      loadResource(resourceId); 
     } 
    } 

    /* implements the rest of the original algorithm */ 
} 

再次,這是不難上述從與回調事件工作改變(我寧願在實踐中,但它是很難寫爲例如短碼)。

重要的是看看上面兩種抽象方法如何封裝原始算法。這樣你可以量身定製滿足你需求的方法。

在最終抽象的主要決定因素將取決於:

  • 誰知道資源的狀態...調用上下文或服務抽象?
  • 你是否需要一箇中心位置來獲取...的資源以及使得這個中心位置在整個程序中都可用的麻煩(呃...單身人士)
  • 你的程序的加載需求真的很複雜嗎? (例如,可以以這樣的方式編寫該抽象,使得在資源列表可用之前不會執行該功能)。
0

在我的一個項目中,我構建了基本上是包裝類的自定義加載器。我正在發送它的元素數組加載和等待完成或失敗的事件(我進一步修改它,並增加了優先級)。所以我不必爲所有資源添加如此多的處理程序。

您只需要監視哪些資源已被下載,以及何時完成所有資源,調度自定義event-resourceDownloaded或其他resourcesFailed。

你也可以在每個資源上加上一個標誌,說明它是必要的還是強制的,如果不是強制的,不要在失敗的資源上拋出失敗的事件並繼續監視其他資源!

現在優先考慮,你可以有一堆你想先顯示的文件,顯示並繼續在後臺加載其他資源。

你可以這樣做,相信我你會喜歡它!

0

您可以檢查Masapi框架,看它是否滿足您的需求。

您還可以調查源代碼以瞭解他們如何解決問題。

http://code.google.com/p/masapi/

這是很編寫和維護。我在使用Air開發的桌面RSS客戶端中成功使用了它。

它的工作非常好,假設您在並行加載太多資源時注意開銷。