Есть длинный js сценарий - просто очень длинная функция. Мне нужно сделать прелоадер для этой функции. Пока функция работает, отображается прелоадер. Когда функция завершилась, прелоадер скрывается.
Но как понять, что функция выполнилась, ничего не вызывая внутри нее? then / await / promice / callback - это ничего не работает и с логической точки зрения бред.
Как заставить функцию Б выполняться только после того, как функция А полностью завершилась?
Сергей в случае запуска таймера - никак не отследить. С точки зрения JS, функция заканчивает работать когда последняя ее команда отрабатывает, а то что в теле функции могут быть запущены таймеры которые в какой то момент запустят другую функцию Х (которая может быть и анонимной), так это уже другая функция будет работать, ту что вы пытаетесь отследить уже давно закончит работать. Т.е. в данном случе вам нужно следить не за завершением функции А, а за завершением функции Х и если она определена в теле функции А которую вам нельзя менять, то тут надо искать другой подход, к примеру отслеживать, что эта функция Х делает и от этого уже отталкиваться.
Первая функция должна как-то по завершению повлиять на глобальное окружение, будь то разметка страницы или переменные. Иначе, без внедрения контролирующего кода прямо в функцию, завершение не отследить. А вторую функцию обернуть в какой-нибудь таймер с проверкой того условия из окружения.
> Все отрабатывает, пока функция еще не завершена
Попробуйте всё же понять одну простую вещь: функция завершена. Запущенные таймеры и прочая асинхронщина это уже совсем другие функции.
Lynn «Кофеман», там нет ни того, ни другого (вроде как). Но допустим...
Как тогда понять, что, если в конце функции обычный цикл (для замедления),
for(var i=0; i<100000; i++) {
console.log(i);
}
она вообще прелоадер не запускает? Сначала выполняется весь цикл, потом мелькает на секунду прелоадер и исчезает. Это не похоже на нормальный ход вещей.
Megas, там просто много операций с текстом типа этого:
// Авто подчеркивание для жирного текста
reg_exp = new RegExp('(<strong>[^<]+<\/strong>)', 'gi');
matches = content.matchAll(reg_exp);
matches = Array.from(matches);
//console.log('Найденые фрагменты', matches);
content = content.replace(reg_exp, '<span style="text-decoration: underline;" data-mce-style="text-decoration: underline;">$1</span>');
ed.setContent(content);
много таких кусков.
Я добавил в конец цикл для теста - прелоадер появляется и исчезает только после того, как завершится цикл. Несмотря на то, что я его вызвал раньше - первой строчкой. Как это понять?
Сергей, мдя.
JS в браузере однопоточный и если кто-то запустил бесконечный цикл, то весь мир (в том числе ваш прелоадер) «зависнет» пока этот цикл не завершится.
Так что это нормальный (для JS в браузере) ход вещей.
В каждом первом учебнике пишут что вредно запускать в основном треде тяжёлые вычисления.
Сергей Сергей, Короче, всем спасибо. Проблему решил, но более хитрым образом. Ваша наводка про окружение помогла ;)
Поскольку скрипт постоянно делает перестановки в редакторе ВП, то я просто через интервал сравниваю текущий текст с предыдущим. И если они соответствуют, значит ничего не изменялось. Следовательно, функция полностью завершена.
// Проверка состояния
var old_content = ed.getContent();
var tracking = setInterval(function(){
var new_content = ed.getContent();
console.log(old_content == new_content);
if(old_content == new_content) {
preloader_screen(false);
clearInterval(tracking);
} else {
console.log('Текст в обработке...');
}
old_content = new_content;
}, 1000);
Rsa97, даже не знал, что такое бывает, если честно. Но это не подошло бы. Оно срабатывает, когда элемент изменяется, а для прелоадера надо срабатывание, когда он перестает изменяться. Через интервал пока самое вменяемое, что придумал