Есть функция JavaScript, из-за которой у меня нулевой контроль над кодом, которая вызывает функцию, которую я написал. Моя функция использует DOM для генерации iFrame, определяет его src и затем добавляет его к другому элементу DOM. Однако, прежде чем моя функция вернется и, таким образом, позволит продолжить выполнение содержащей функции, обязательно, чтобы iFrame был полностью загружен.
Вот вещи, которые я пробовал и почему они не работают:
1. Опция SetTimeout:
99,999% случаев, это ответ. На самом деле, в последнее десятилетие, которым я занимался наставничеством в JavaScript, я всегда настаивал на том, чтобы код всегда мог быть подвергнут рефакторингу, чтобы использовать эту опцию, и никогда не думал, что существует сценарий, где это не так. Ну, я наконец-то нашла одну! Проблема заключается в том, что, поскольку моя функция вызывается как встроенная, если следующая строка выполняется до того, как мой iFrame завершит загрузку, она полностью нейтрализует мой сценарий, и с того момента, как мой сценарий завершается, внешний сценарий продолжается. Сортировка вызовов не будет работать
2. Цикл «Ничего не делать»:
Эта опция используется в то время как (// iFrame не загружен) {// ничего не делать}. Теоретически это не вернется, пока кадр не будет загружен. Проблема в том, что, так как это потребляет все ресурсы, iFrame никогда не загружается. Этот трюк, хотя и ужасно непрофессиональный, грязный и т. Д., Будет работать, когда вам просто нужна внутренняя задержка, но, поскольку мне требуется внешний поток для завершения, он не будет.
В FF через несколько секунд он останавливает выполнение сценария и появляется предупреждение о том, что существует сценарий, не отвечающий на запросы. Пока это оповещение активировано, iFrame может загрузить, а затем моя функция может вернуться, но браузер завис на 10 секунд, а затем требует, чтобы пользователь корректно отклонил ошибку, - нет дела.
3. Модель диалога:
Я был вдохновлен тем фактом, что всплывающее окно FF позволяло загружать iFrame, останавливая выполнение функции, и, подумав об этом, я понял, что это потому, что модальный диалог - это способ остановки выполнения, позволяющий другим потокам продолжать работу. ! Блестящий, поэтому я решил попробовать другие модальные варианты. Такие вещи, как alert () работают прекрасно! Когда он всплывает, хотя бы только на 1/10 секунды, iFrame может завершиться, и все прекрасно работает. И на случай, если 1/10 секунды не достаточно, я могу поместить диалог модели в цикл while из решения 2, и это обеспечит своевременную загрузку iFrame. Сладкий, верно? За исключением того факта, что теперь мне нужно вывести очень непрофессиональный диалог, чтобы пользователь мог его закрыть, чтобы запустить мой скрипт. Я боролся с собой за эту цену / выгоду от этого действия, но затем я столкнулся со сценарием, когда мой код вызывался 10 раз на одной странице! Необходимость отклонить 10 предупреждений перед доступом к странице ?! Это напоминает мне о страницах детского сценария конца 90-х, и это НЕ вариант.
4. Еще один сценарий задержки gazillion:
Существует около 10 функций jQuery delay или sleep, некоторые из них на самом деле довольно умно разработаны, но ни одна из них не сработала. Несколько вариантов прототипа, и опять же, ни один из найденных мной не смог бы это сделать! Около дюжины других библиотек и фреймворков утверждали, что у них есть то, что мне нужно, но, увы, все они сговорились, чтобы дать мне ложную надежду.
Я убежден, что, поскольку встроенный диалог моделей может остановить выполнение, в то же время позволяя другим потокам продолжаться, должен быть некоторый доступный код способ сделать то же самое без ввода данных пользователем.
Код буквально тысячи и тысячи строк и является частной собственностью, поэтому я написал этот небольшой пример проблемы, с которой вы можете работать. Важно отметить, что ТОЛЬКО код, который вы можете изменить, находится в функции onlyThingYouCanChange
Тестовый файл:
<html>
<head>
</head>
</html>
<body>
<div id='iFrameHolder'></div>
<script type='text/javascript'>
function unChangeableFunction()
{
new_iFrame = onlyThingYouCanChange(document.getElementById('iFrameHolder'));
new_iFrame_doc = (new_iFrame.contentWindow || new_iFrame.contentDocument);
if(new_iFrame_doc.document)new_iFrame_doc=new_iFrame_doc.document;
new_iFrame_body = new_iFrame_doc.body;
if(new_iFrame_body.innerHTML != 'Loaded?')
{
//The world explodes!!!
alert('you just blew up the world! Way to go!');
}
else
{
alert('wow, you did it! Way to go!');
}
}
var iFrameLoaded = false;
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
unChangeableFunction();
</script>
</body>
blank_frame.html:
<html>
<head>
</head>
<body style='margin:0px'>Loaded?</body>
</html>
ЗДЕСЬ ОТВЕТ, КОТОРЫЙ Я СДЕЛАЛ ИЗ КОМБИНИРОВАННЫХ ИДЕЙ ОТ РЕСПОНДЕРОВ!ВЫ, ребята, ROCK!
новый источник функции, которую мне было разрешено изменить:
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
if (window.XMLHttpRequest)
{
AJAX=new XMLHttpRequest();
}
else
{
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX)
{
AJAX.open("GET", 'slow_page.php', false);
AJAX.send(null);
}
else
{
alert('something is wrong with AJAX!');
}
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
slow_page.php:
<?
usleep(100000);//sleep for 1/10th of a second, to allow iFrame time to load without DOSing our own server!
?>
Я хочу отметить, что язаявил, что нет ничего кроме этой функции, которую я мог бы изменить, и добавление страницы php нарушало это «правило», но в моём случае я смог это сделать.Если бы я не смог этого сделать, я бы мог бы вызывать blank_frame.html вместо slow_page.php, и он должен был бы вызываться только один раз (так 2 раза за загрузку кадра), предполагая, что этоответил за то же время, что и загрузка iFrame.Если по какой-либо причине загрузка iFrame была медленнее, он мог бы назвать ее 2ce (всего 3 обращения к серверу)