Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 17.07.2018, 11:25
Интересующийся
Отправить личное сообщение для ice99 Посмотреть профиль Найти все сообщения от ice99
 
Регистрация: 19.06.2011
Сообщений: 20

UI progressbar не обновляется на экране
Значит так. Не сильно уверен, что это правильная тема, но всё-таки спрошу.
Пишу скрипт для After Effects на ExtendedScript (диалект ECMAScript Javascript и ActionScript ). Сильно похож на Javascript, однако.

Проблема в следующем. У меня есть основная задача скрипта, которая выполняется в основном цикле. Количество шагов цикла мне известно. Допустим их 10. Я хочу чтобы текстовая метка UI вела себя так:
1/10,2/10,...,10/10

Внутри цикла обновляю метку счетчиком цикла. Так вот итоговое UI скачет или сразу 1/10->10/10, или успевает показать 2/10. В любом случае не выводит информацию обо всех шагах цикла. Такое ощущение, как "подвисает". Подозреваю что основной цикл ей просто "не даёт слова". Если вставлять в основной цикл "alert", то UI обновляется.

Как это победить?
Код ниже

//Это счетчик - простая текстовая метка
    var counter = new Window("palette");  
    counter.prompt = counter.add("statictext",[0,0,180,20]);  
    counter.prompt.text = "Script is running";


Ниже цикл (убрал всё ненужное)

for (i = 1; i <= NumOfStrings; i++) { в  
    counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames");  
    counter.update();   
    // Здесь основной цикл
    }
Ответить с цитированием
  #2 (permalink)  
Старый 17.07.2018, 11:33
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 27.11.2015
Сообщений: 2,899

Сообщение от ice99
Внутри цикла обновляю метку счетчиком цикла
Внутри которого?
У вас цикл в цикле?
Ответить с цитированием
  #3 (permalink)  
Старый 17.07.2018, 11:44
Интересующийся
Отправить личное сообщение для ice99 Посмотреть профиль Найти все сообщения от ice99
 
Регистрация: 19.06.2011
Сообщений: 20

Сообщение от Dilettante_Pro Посмотреть сообщение
Внутри которого?
У вас цикл в цикле?
Если быть точным, то да
for (i = 1; i <= NumOfStrings; i ++) { // Основной цикл

          counter.prompt.text = ("Обработано " + i+" / " + NumOfFrames + " кадров"); //Присвоение тексту счетчика нового значения
          counter.update();  // Рефреш UI? который по идее должен работать   

          for (j = 0; j < ProjectCount; j++) { // Внутренний цикл
     
          }

      }
Ответить с цитированием
  #4 (permalink)  
Старый 17.07.2018, 11:57
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 27.11.2015
Сообщений: 2,899

ice99,
NumOfStrings или NumOfFrames?

Вложенный цикл должен выполниться NumOfStrings раз?
Во вложенном цикле, случайно, не меняются i или NumOfStrings?
Ответить с цитированием
  #5 (permalink)  
Старый 17.07.2018, 12:03
Интересующийся
Отправить личное сообщение для ice99 Посмотреть профиль Найти все сообщения от ice99
 
Регистрация: 19.06.2011
Сообщений: 20

Сообщение от Dilettante_Pro Посмотреть сообщение
ice99,
NumOfStrings или NumOfFrames?

Вложенный цикл должен выполниться NumOfStrings раз?
Во вложенном цикле, случайно, не меняются i или NumOfStrings?
Нет,нет, нет.
ТОЛЬКО ЧТО. У меня скрипт отработал нормально, прошёл от 1 до 10. Думал "победа". Но нет. Тут же запускаю и 1,2,пауза,10.
Еще раз повторюсь, если перед
counter.update();

ставить
alert ("Hi!") // или alert (i);
counter.update();


То counter отрабатывает отлично 1,2,3,4,5,6,7,8,9,10.

Ставил
$.sleep(100);

не помогает

Может дело в синхронном\асинхронном выполнении?
Ответить с цитированием
  #6 (permalink)  
Старый 17.07.2018, 12:32
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 27.11.2015
Сообщений: 2,899

Сообщение от ice99
Может дело в синхронном\асинхронном выполнении?
Скорее всего, да. Цикл не ждет завершения counter.update();

Не знаю этого пакета - может, там есть средства заставить работать в синхронном режиме?
Ответить с цитированием
  #7 (permalink)  
Старый 17.07.2018, 13:53
Интересующийся
Отправить личное сообщение для senex Посмотреть профиль Найти все сообщения от senex
 
Регистрация: 09.12.2014
Сообщений: 10

Мало знаком с этим диалектом, но свое мнение выскажу.

Цикл for работает очень быстро, а метод .update() медленно, поскольку пропускается через большую библиотеку. Поэтому цикл for успевает сделать все 10 обновлений prompt.text, пока выполнится 2 или 3 итерация update(). Все последующие итерации update() тоже срабатывают, но этого не видно, поскольку все они показывают последнее 10-е обновление prompt.text.

Оптимальное решение, если update() принимает callback-функцию (нужно смотреть документацию). Тогда .prompt.text каждый раз будет обновляться только после выполнения очередного .update()

for (i = 1; i <= NumOfStrings; i++) {
    var fn = function(i) {
       counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames");
    }  
    counter.update(fn);  
    // Здесь основной цикл
}



Если callback-функции не предусмотрено, то можно использовать setTimeOut или что его заменяет в данном диалекте:

for (i = 1; i <= NumOfStrings; i++) {
    var fn = function(i) {
       counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames");
    }

    setTimeOut(fn, 12);

    counter.update();  
    // Здесь основной цикл
}


Но это конечно хуже. Задержку можно подобрать методом проб. или замерить в консоли время выполнения .update()


Все. Где-то так

Последний раз редактировалось senex, 17.07.2018 в 14:01.
Ответить с цитированием
  #8 (permalink)  
Старый 17.07.2018, 14:13
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 27.11.2015
Сообщений: 2,899

senex,
Все эти танцы с бубном в данном случае не помогут:
в цикле быстренько позапустятся все функции или таймауты, и исполнятся они практически одновременно.
Таймаут не задерживает выполнение цикла, а задерживает выполнение функции, указанной в нем.
Помочь может только рекурсивное выполнение таймаута.
var i = 0;
function fn() {
   i++;
   counter.prompt.text = ("Processed " + i+" / " + NumOfFrames + " frames");
   counter.update();
   // вложенный цикл
   if(i < NumOfStrings) setTimeout(fn, 1000);
}
fn();

setTimeout в ExtendScript нет, но можно написать через sleep
$.setTimeout = function(func, time) {
        $.sleep(time);
        func();
};
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
AngularJS не обновляется таблица. Нужна помощь Георгий4134 Общие вопросы Javascript 1 05.12.2017 14:26
Progressbar с таймером. Feex Элементы интерфейса 22 21.02.2016 23:55
Не обновляется контент после повторного добавления данных в историю браузера grach28rus AJAX и COMET 3 22.09.2015 04:47
Счетчик кликов в progressbar ksmnvt Элементы интерфейса 1 18.10.2013 08:10
Виснет progressbar Eser Общие вопросы Javascript 0 04.07.2012 13:46