2011-07-13 42 views
0

我想使用itemFileReadStore將查詢結果保存到一個名爲boxes的數組中,但返回值爲空(大概是因爲fetch是異步運行的)。與ItemFileReadStore查詢異步混淆

gotItems函數根據需要構建數組,但我無法將其返回給我自己以供任何使用!我可以將剩餘的功能構建到gotItems部分,但這會使我的代碼變得沒有問題。

如何從gotItems函數返回一個通用的JavaScript數組?

function getContentFile() { 
    contentStore = new dojo.data.ItemFileReadStore({ 
    url: '../config/content.json', 
preventCache : true 
    }); 

    var boxes = new Array(); 
    contentStore.fetch({query: {partner : 'enabled'}, onItem: gotItems }); 
    return boxes; 
} 

function gotItems(item) { 
    boxes.push(contentStore.getValue(item,'title')); 
    console.log(boxes); 
    return boxes; 
} 

dojo.addOnLoad(function() { 
    boxes = getContentFile(); 
    console.log(boxes); 
    fadeIn('header', 500, 0); 
}); 

回答

0

歡迎來到異步操作的世界。

你需要用「繼續式」編程來完成。 ItemFileReadStore的提取操作是異步的 - 正如你已經知道的,通過傳遞gotItems延續它。

contentStore.fetch({query: {partner : 'enabled'}, onItem: gotItems })將立即返回。您的boxes在此時將爲空(因爲JavaScript是單線程的)。數據到達後執行gotItems,然後後續返回到傳遞給dojo.addOnLoad的函數。

你必須把你的處理代碼:

console.log(boxes); 
    fadeIn('header', 500, 0); 

延續gotItems自身內部。例如,像:

function gotItems(item) { 
    var boxes = []; 
    dojo.forEach(item, function(box) { 
    boxes.push(contentStore.getValue(box,'title')); 
    }); 
    console.log(boxes); // You probably need to store "boxes" somewhere instead of just logging it 
    fadeIn('header', 500, 0); 
} 

而且,傳遞給onItems的數據是一個數組,所以你需要遍歷它。

0

當函數返回時,您無法訪問結果,因爲按照您的猜測,fetch操作是異步執行的。

您可以將使用結果的代碼放入您的gotItems()函數(由Stephen回答),也可以使用Deferreds和Promises。恕我直言,這是一個更好的選擇,因爲它可以讓你更好地組織你的代碼(一旦你習慣了處理promise的習慣用法,代碼會更自然地閱讀),它允許你透明地執行同步和異步操作。

請參閱thesetwo Dojo關於此主題的教程。

在你的情況,涉及deferreds一個可能的解決辦法讀到這樣:

function getContentFile() { 
    contentStore = new dojo.data.ItemFileReadStore({ 
    url: '../config/content.json', 
    preventCache: true 
    }); 

    var dfd = new dojo.Deferred(); 
    var boxes = new Array(); 
    contentStore.fetch({ 
    query: { partner : 'enabled' }, 
    onItem: function(item) { 
     boxes.push(contentStore.getValue(item,'title')); 
    }, 
    onComplete: function() { 
     // resolve the promise and execute the function in then() 
     dfd.callback(boxes); 
    } 
    }); 
    return dfd; 
} 

dojo.addOnLoad(function() { 
    getContentFile().then(function(boxes) { 
    console.log(boxes); 
    fadeIn('header', 500, 0); 
    }); 
});