2013-07-03 83 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后,我偶然发现了队列,我认为这是要走的路。只要我设法用队列来实现它,我会将你的答案标记为已接受的答案。非常感谢! –