2013-11-22 77 views
0

我想設計一個個人應用程序,它異步加載數據,然後根據Windows 8.1商店應用程序顯示一個網格。等待初始化直到數據異步加載

我遇到了問題,我的用戶界面試圖在我的數據加載之前執行。

我當前的代碼:

(function() { 
"use strict"; 
var asyncInProgress = true; 
var groupedItems; 
var list; 
var observable; 
var matches = new WinJS.Binding.List(); 
var matchGroups = new WinJS.Binding.List(); 
var BattleGrounds = new WinJS.Binding.List(); 

list = getData(); 
initGroups(list); 

function initGroups(l) { 
    var groupedItems = list.createGrouped(
     function groupKeySelector(item) { return item.group.key; }, 
     function groupDataSelector(item) { return item.group; } 
    ); 
} 

WinJS.Namespace.define("Data", { 
    Observable: WinJS.Class.define(function() { 
     this.dispatch = function() { 
      this.dispatchEvent("dataReady"); 
     } 
    }), 
    getObservable: getObservable, 
    items: groupedItems, 
    groups: groupedItems.groups, 
    getItemReference: getItemReference, 
    getItemsFromGroup: getItemsFromGroup, 
    resolveGroupReference: resolveGroupReference, 
    resolveItemReference: resolveItemReference, 
    updateData: updateData, 
    getAsyncStatus: getAsyncStatus 
}); 

WinJS.Class.mix(Data.Observable, WinJS.Utilities.eventMixin); 
WinJS.Class.mix(Data.Observable, WinJS.Utilities.createEventProperties("dataReady")); 

// Provides support for event listeners. 
function getObservable() { 
    observable = new Data.Observable(); 
    return observable; 
} 

// Get a reference for an item, using the group key and item title as a 
// unique reference to the item that can be easily serialized. 
function getItemReference(item) { 
    return [item.group.key, item.title, item.backgroundImage]; 
} 

// This function returns a WinJS.Binding.List containing only the items 
// that belong to the provided group. 
function getItemsFromGroup(group) { 
    return list.createFiltered(function (item) { return item.group.key === group.key; }); 
} 

// Get the unique group corresponding to the provided group key. 
function resolveGroupReference(key) { 
    return groupedItems.groups.getItemFromKey(key).data; 
} 

// Get a unique item from the provided string array, which should contain a 
// group key and an item title. 
function resolveItemReference(reference) { 
    for (var i = 0; i < groupedItems.length; i++) { 
     var item = groupedItems.getAt(i); 
     if (item.group.key === reference[0] && item.title === reference[1]) { 
      return item; 
     } 
    } 
} 

function updateData() { 
    asyncInProgress = true; 
    BattleGrounds.splice(0, matches.length); 
    BattleGrounds._currentKey = 0; 
    groupedItems = null; 
    list = getData(); 
    initGroups(list); 
} 

function getAsyncStatus() { 
    return asyncInProgress; 
} 

function getData() { 
    var darkGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY3B0cPoPAANMAcOba1BlAAAAAElFTkSuQmCC"; 
    var lightGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC"; 
    var mediumGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC"; 

    var url = 'https://api.guildwars2.com/v1/wvw/matches.json'; 

    acquireSyndication(url).then(function (response) { 

     // Remove any invalid characters from JSONp response. 
     var fixedResponse = response.responseText.replace(/\\'/g, "'"); 
     var jsonObj = JSON.parse(fixedResponse); 

     jsonObj.wvw_matches.forEach(function (battle) { 
      var anet_id = value.wvw_match_id; 
      // Create Group 
      var matchGroup = { 
       key: anet_id, 
       title: anet_id 
      }; 

      matchGroups.push(matchGroup); 

      // Get Details 
      acquireSyndication("https://api.guildwars2.com/v1/wvw/match_details.json?match_id=" + anet_id).then(function (json) { 
       var fixedJson = json.responseText.replace(/\\'/g, "'"); 
       var obj = JSON.parse(fixedJson); 
       fixedJson.maps.forEach(function (value) { 
        BattleGrounds.push({ 
         group: matchGroup, key: matchGroup.title, title: value.type, 
         subtitle: value.type, map: "eb", description: "NA", content: "NA", "type": value.type, 
         "scores": value.scores, "objectives": value.objectives, "bonuses": value.bonuses, backgroundImage: lightGray 
        }); 
       }); 
      }, function (error) { 

       var x = error.getAllResponseHeaders(); 
       var matchGroup = matchGroups[0]; 

       for (var i = 0; i < matchGroups.length; i++) { 
        flickrPosts.push({ 
         group: matchGroups[i], key: matchGroup.title, title: "Error loading", 
         subtitle: "Error", backgroundImage: lightGray, published: "N/A", description: "N/A" 
        }); 
       } 

       asyncInProgress = false; 
       observable.dispatch(); 

      }); 
     }); 

    }, function (error) { 

     var x = error.getAllResponseHeaders(); 
     var matchGroup = matchGroups[0]; 

     for (var i = 0; i < matchGroups.length; i++) { 
      flickrPosts.push({ 
       group: matchGroups[i], key: matchGroup.title, title: "Error loading", 
       subtitle: "Error", backgroundImage: lightGray, published: "N/A", description: "N/A" 
      }); 
     } 

     asyncInProgress = false; 
     observable.dispatch(); 

    }); 
    return BattleGrounds; 
} 

function acquireSyndication(url) { 
    return WinJS.xhr({ 
     url: url, 
     headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" } 
    }); 
} 
})(); 

在組這樣的錯誤了:groupedItems.groups。其中說組是未定義的。 我知道這是因爲數據仍在處理中。

我該如何解決這個問題? 我看了一下承諾對象,但整個概念讓我感到困惑,因爲我對Windows 8應用程序的基礎結構知之甚少。

+0

使用在ajax返回時執行的回調函數。 –

+0

我的代碼的哪一部分放在那裏?除「變量」聲明和init之外的所有內容?所有其他頁面使用「數據」對象 – Puzzle84

+0

耶依賴於數據的一切。或者你可以使ajax同步,以便它保持執行直到完成。 –

回答

1

問題的核心在於getData()函數 - 它不會返回數據,因爲它使用異步調用來獲取數據。數據在返回時尚不可用。看起來該函數會進行多次異步調用來獲取數據(使用acquireSyndication())。當這些異步功能在未來某個時間完成時,然後您將該數據放入matchGroups,然後在acquireSyndication()的更多呼叫之後放入BattleGrounds

你在做什麼是相當混亂,所以沒有一個簡單的修復。從概念上講,您需要從異步代碼的完成處理程序處理BattleGrounds數據,並且使用它的所有代碼必須從該完成處理程序內繼續,而不是在getData()調用之後繼續。您不能撥打getData(),並將其用作同步功能,因爲它是異步的。這需要異步編程技術。

如果您正在進行多個異步調用並嘗試在所有這些調用完成後執行一些操作(我認爲是您正在執行的操作),那麼您還需要專門針對該情況編寫代碼。你可以使用承諾,或者你可以保存一個計數器,在每個完成函數中有多少個Ajax調用,你遞增計數器,看看這是否是剛完成的最後一個,如果是,那麼你可以處理所有數據並繼續執行其餘的代碼。

我也建議你不要在函數的某個部分使用promise,然後在下一部分使用completion函數。使用其他的,而不是混合,來保持你的代碼清潔。