Невозможная встроенная задержка / сон Javascript

Есть функция JavaScript, код которой у меня нет контроля, которая вызывает функцию, которую я написал. Моя функция использует DOM для создания iFrame, определяет его src, а затем добавляет его к другому элементу DOM. Однако до того, как моя функция вернется и, таким образом, позволит продолжить выполнение содержащейся функции, обязательно, чтобы iFrame был полностью загружен.

Вот вещи, которые я пробовал, и почему они не работают:

1. Параметр SetTimeout:
В 99,999% случаев это ИТОГ. Фактически, в последнее десятилетие, когда я обучал JavaScript, я всегда настаивал на том, чтобы код всегда можно было реорганизовать для использования этой опции, и никогда не верил, что существует сценарий, в котором это не так. Ну вот наконец-то нашел! Проблема в том, что, поскольку моя функция вызывается встроенной, если следующая строка выполняется до того, как мой iFrame завершает загрузку, она полностью нейтрализует мой сценарий, и с момента завершения моего сценария внешний сценарий продолжается. Обратный вызов не будет работать

2. Цикл «Ничего не делать»:
Эту опцию вы используете while (// iFrame не загружен) {// ничего не делать}. Теоретически это не вернется, пока кадр не будет загружен. Проблема в том, что поскольку при этом потребляются все ресурсы, iFrame никогда не загружается. Этот трюк, хотя и ужасно непрофессиональный, грязный и т. Д., Будет работать, когда вам просто нужна встроенная задержка, но поскольку мне требуется внешний поток для завершения, этого не произойдет.
В FF через несколько секунд он приостанавливает скрипт и появляется предупреждение о том, что сценарий не отвечает. Пока это предупреждение активировано, iFrame может загружаться, а затем моя функция может возвращаться, но заморозить браузер на 10 секунд, а затем потребовать, чтобы пользователь правильно отклонил ошибку, - не годится.

3 . Диалог модели:
Меня вдохновил тот факт, что всплывающее окно FF позволяло загружать iFrame, останавливая выполнение функции, и, подумав об этом, я понял, что это потому, что модальный диалог - это способ остановки выполнение, но позволяет другим потокам продолжать! Великолепно, поэтому я решил попробовать другие модальные варианты. Такие вещи, как alert () прекрасно работают! Когда он всплывает, даже если он появляется только на 1/10 секунды, iFrame может завершить работу, и все работает отлично. И на всякий случай, если 1/10 секунды недостаточно, я могу поместить диалог модели в цикл while из решения 2, и это обеспечит своевременную загрузку iFrame. Сладкое правда? За исключением того факта, что теперь мне нужно открыть очень непрофессиональный диалог, который пользователь должен закрыть, чтобы запустить мой скрипт. Я боролся с самим собой по поводу затрат / выгод этого действия, но затем я столкнулся со сценарием, когда мой код вызывается 10 раз на одной странице! Необходимость отклонять 10 предупреждений перед открытием страницы ?! Это напоминает мне детские страницы со сценариями конца 90-х, и это НЕ вариант.

4. Существует множество других сценариев задержки:
Существует около 10 функций задержки или ожидания jQuery, некоторые из них были разработаны весьма умно, но ни один из них не работал. Несколько вариантов прототипа, и снова ни один из найденных мною не справился с этим! Около дюжины других библиотек и фреймворков заявили, что у них есть то, что мне нужно, но, увы, все они сговорились, чтобы дать мне ложную надежду.

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

Код буквально состоит из тысяч и тысяч строк и является частным, поэтому я написал этот небольшой пример проблемы, чтобы вы могли работать с ним. Важно отметить, что ЕДИНСТВЕННЫЙ код, который вы можете изменить, находится в функции 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>


ЗДЕСЬ ОТВЕТ, КОТОРЫЙ Я ПОЛУЧИЛ ИЗ ОБЪЕДИНЕНИЯ ИДЕЙ ОТ ОТВЕТОВ! ВЫ, ПАРНИ, РОК!
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 обращения к серверу)

8
задан trex005 2 January 2011 в 01:17
поделиться