2013-07-03 3 views
0

Я не могу понять это самостоятельно и вам нужна ваша помощь. Я работаю с вложенными базовыми объектами в приложении phonegap и хочу сохранить их все. Во время сохранения я хочу показать анимацию загрузки. Когда все будет сохранено, я хочу продолжить следующую страницу/шаг. Я уже достиг этого, но анимация не работает, потому что мои циклы сохранения блокируют все обновления пользовательского интерфейса. (Я сохраняю в localStorage, а не через ajax.) Поэтому я попытался замедлить сохранение, вставив таймауты между сохранением каждого элемента. Теперь сохранение задерживается, но inteface продолжает следующую страницу, прежде чем все будет сохранено. Мои обратные вызовы, похоже, настроены неправильно.Как проходить через вложенные объекты с задержкой

Знаете ли вы образец для чистых вложенных обратных вызовов?

Я собрал 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

все еще пытается понять, что вы имеете в виду. :-) У меня есть два вложенных цикла, если вы внимательно посмотрите на них. для каждого дерева, для каждого листа. как бы вы к трюку? –

+0

Если бы у меня был только один цикл, вы были правы (если бы я правильно вас понял ...). Для одного цикла setTimeout не изменяет последовательность (если это слово :-)) –

ответ

0

Я думаю, вы должны использовать .sort() метод, и вы должны добавить свои собственные параметры этого метода. Это даст вам представление: How may I sort a list alphabetically using jQuery? http://james.padolsey.com/javascript/sorting-elements-with-jquery/

+0

Hi Lightsaber. Я не вижу, как сортировка мне поможет. Я на самом деле не хочу сортировать вещи, но собирает коллекции объектов детерминированным, но отложенным образом. –

+0

Я вижу, что вы были введены в заблуждение моим глупым примером. Нумерация - это только показать порядок выполнения, которого я хочу. –

0

я придумал с добавлением обратного вызова к самому длинному коллекции. Таким образом, обратный вызов возникает после того, как все было обработано.

В функции отсроченного исполнения я делаю это:

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

Так не последняя обработанная коллекция получает обратный вызов, но самую большую коллекцию.

См. here.

Что вы думаете об этом решении?

Если у вас есть идея, напишите ответ.

1

Если я понимаю, чего вы пытаетесь достичь, и я думаю, что могу (но, может быть, и ошибаюсь), не лучше ли вам с моделью очереди?

Вам нужно установить Timout(), по сути, только для запуска событий пользовательского интерфейса, чтобы вы получали обновления. Это не должно быть очень долго, 0 мс или 1 мс (просто в случае оптимизации) было бы неплохо.

Что бы я делал, это одна функция обратного вызова, которая берет один листовой элемент из одного из ваших списков, обрабатывает его, а затем снова перепланирует работу с setTimeout() каждый раз, если еще предстоит сделать больше работы.

Таким образом, ваши операции будут обрабатываться последовательно. Я не думаю, что вы хотели, чтобы они работали параллельно, хотя похоже, что это то, что происходит. Таким образом, ваши обратные вызовы также будут сериализованы.

Я знаю, что вы создали надуманный пример, чтобы продемонстрировать проблему настолько просто, насколько это возможно, но это немного сложно понять, что вы пытаетесь сделать, но есть ли у меня это право?

+0

Вы абсолютно правы. Я наткнулся на очереди, а после публикации моего собственного anser здесь, и я думаю, что это путь. Как только мне удастся реализовать его с очередями, я буду отмечать ваш ответ как принятый. Большое спасибо! –

Смежные вопросы