2013-07-03 80 views
0

我不能單獨弄清楚這一點,需要你的幫助。 我正在使用phonegap應用程序嵌套的主幹對象,並且想要將它們全部保存。在保存時,我想顯示一個加載動畫。當一切都保存時,我想繼續下一頁/步驟。 我已經實現了這一點,但動畫無效,因爲我的保存循環阻止了所有UI更新。 (我保存到localStorage,而不是通過ajax。)所以我試圖通過在保存每個項目之間插入超時來減慢儲存。現在保存被延遲了,但是在一切都被保存之前,接口繼續到下一頁。我的回調似乎設置不正確。如何通過延遲迭代嵌套對象

你知道一個乾淨的嵌套回調模式嗎?

我已經放在一起a fiddle that illustrates my problem

你能幫我解決它,使之以正確的順序創建警報:A1, A2, A3, A4, A5, A6, A7, B1, B2, B3, Everything is finished

非常感謝提前。

這裏,如果你不想看看小提琴代碼:

var forest = { 
    "trees": [{ 
     "id": "tree A", 
      "leaves": [{ 
      "name": "A1" 
     }, { 
      "name": "A2" 
     }, { 
      "name": "A3" 
     }, { 
      "name": "A4" 
     }, { 
      "name": "A5" 
     }, { 
      "name": "A6" 
     }, { 
      "name": "A7" 
     }] 
    }, { 
     "id": "tree B", 
      "leaves": [{ 
      "name": "B1" 
     }, { 
      "name": "B2" 
     }, { 
      "name": "B3" 
     }] 
    }] 
}; 

var callback = function() { 
    alert("Everything is finished"); 
}; 

var workOnTree = function (tree, callback) { 
    var leaves = tree.leaves; 
    var leafCount = 0; 
    var delayedAlert = function() { 
     alert(leaves[leafCount].name); 
     leafCount += 1; 
     if (leafCount < leaves.length) { 
      setTimeout(delayedAlert, 1000); 
     } else { 
      if (callback !== undefined && typeof callback == 'function') { 
       callback(); 
      } 
     } 
    }; 
    setTimeout(delayedAlert, 1000); 
}; 

var workOnForest = function (forest, callback) { 
    var trees = forest.trees; 
    var treeCount = 0; 
    var delayedExecution = function() { 
     if (treeCount == (trees.length - 1)) { 
      // for last tree pass callback 
      workOnTree(trees[treeCount], callback); 
     } else { 
      workOnTree(trees[treeCount]); 
     } 
     treeCount += 1; 
     if (treeCount < trees.length) { 
      // this gives a delay between the trees 
      setTimeout(delayedExecution, 1000); 
     } 
    }; 
    setTimeout(delayedExecution, 1000); 
}; 
workOnForest(forest, callback); 
+0

如果您在處理當前的回調函數期間只觸發了setTimeout,那麼它會不會更好?這樣,它們被正確地序列化。 – cirrus

+0

仍試圖瞭解你的意思。 :-)如果仔細觀察,我有兩個嵌套for循環。爲每棵樹,爲每片葉子。你會怎麼做? –

+0

如果我只有一個循環,你是對的(如果我正確理解你的話......)。對於一個循環setTimeout不會改變順序性(如果這是一個詞:-)) –

回答

0

我認爲你應該使用的.sort()方法,你應該添加自己的參數,此方法。這會給你一個想法: How may I sort a list alphabetically using jQuery? http://james.padolsey.com/javascript/sorting-elements-with-jquery/

+0

嗨Lightsaber。我不明白排序會如何幫助我。我其實不想排序,而是以確定性但延遲的方式處理對象的集合。 –

+0

我看到你被我愚蠢的例子誤導了。數字只是爲了顯示我所期望的執行順序。 –

0

我想出了添加回調時間最長的集合。通過這種方式,在處理完所有事件後都會發生回調

在延遲執行功能我這樣做:

if (treeCount == maxLeavesTreeIndex) { 
    // for last tree pass callback 
    workOnTree(trees[treeCount], callback); 
} 

所以不是最後的處理收集得到的回調,但最大的集合。

參見here

您對這個解決方案有什麼看法?

如果您有更好的想法,請提供答案。

1

如果我明白你想達到什麼目的,我想我會這樣做(但我可能是錯的),用Queue模型你不會更好嗎?

您需要setTimout()實質上只是爲了運行UI事件,以便獲取更新。這並不需要很長,0ms或1ms(只是在優化的情況下)會很好。

我會做的只有一個回調函數,它從一個列表中取出一個葉子項目,對它進行處理,然後在每次有更多工作需要時使用setTimeout()重新安排更多的工作。

這樣,您的操作將被連續處理。我不認爲你想讓它們並行運行,儘管看起來就是這樣。所以你的回調也會被序列化。

我知道你已經建立了一個專門用來演示問題的例子,但這會讓你看到你想要做的事情有點棘手,但是我有這樣的想法嗎?

+0

你是對的。在我發佈了自己的anser後,我偶然發現了隊列,我認爲這是要走的路。只要我設法用隊列來實現它,我會將你的答案標記爲已接受的答案。非常感謝! –