2017-02-13 24 views
-3

Решение: Кажется, что проблема была связана с тем, как я вызывал свой механизм очередей в window.onload.Ошибка вызова функции Javascript в голове, но не в теле

Преамбула - Я рад видеть, что меня помещают как дубликат, где решение заключается в использовании window.onload, которое я уже здесь использую. Несколько комментариев указывают на возможные проблемы с очередью, которую я получил от другого решения stackoverflow, но оставляю меня в темноте из-за отсутствия разработки.

Вопрос: Если я делаю вызов функции в голове, он терпит неудачу. Если я делаю вызов функции в теле, он преуспевает. Зачем?

Расширение: Почему успешно выполняются вызовы одной и той же функции в global.js, которая находится выше неудачного вызова?

У меня есть javascript, который создает загрузочную «очередь» сортировки (функция addLoadEvent в global.js). Вызов этой функции добавляет очередь в том случае, когда вызывается onload.

Кроме того, я обнаружил, что вызов конкретной функции сценария завершается с ошибкой, если он находится в голове и в теле. Я не могу понять, почему, потому что все, что необходимо (другие функции js) загружаются над вызовом функции, а фактический вызов функции не запускается до onload, гарантируя наличие необходимых элементов html.

Порядок загрузки:

  1. HTML файл до головы
  2. global.js - в том числе addLoadEvent (FUNC)
    • addLoadEvent x2 (преуспевает)
  3. встроенный скрипт в head - includes initialFighter()
    • addLoadEvent (место один - сбой)
  4. HTML файл после того, как головной
    • addLoadEvent (место два - успешно)
  5. OnLoad запускает в очереди вызовов

Для целей этот вопрос, вызов функции, который терпит неудачу или преуспевает на основе его местоположения, следующий.

addLoadEvent(initialFighter()); 

Вот укороченный HTML-код, обратите внимание, что отмечены 2 местоположения. Если я скопирую вставку вышеуказанного вызова функции на место 1, он терпит неудачу. Если я скопирую вставку вышеприведенного вызова функции в «Место два», он будет успешным.

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <script src="global.js"></script> 
    <script type="text/javascript"> 
    function showFighter(id) { 
    var pic = document.getElementById("picture"); 
    var picPath = 'url(images/' + id + '.png)'; 
    pic.style.backgroundImage = (picPath); 
    } 
    function initialFighter() { 
    var fighter = getURLParameter('fighter'); 
    if (typeof(fighter) != "undefined" && fighter != null) { 
     showFighter(fighter); 
    } else { 
     showFighter('Foobar'); 
    } 
    } 
    ***** LOCATION ONE ***** 
    </script> 
</head> 
<body> 
<header></header> 
<nav id="nav"></nav> 
<section id="fighters"> 
    <div id="picture"></div> 
    <div id="text"></div> 
    <script type="text/javascript"> 
    ***** LOCATION TWO ***** 
    </script> 
</section> 
<footer id="footer"></footer> 
</body> 
</html> 

Ниже global.js, который является очень первый файл сценария загружен:

Обратите внимание, что есть 2 addLoadEvent (FUNC) вызывает здесь, и они преуспевают (не запускаются, пока HTML элементов существуют), несмотря на то, что они превышают практически все остальное.

function addLoadEvent(func) { 
    var prevOnLoad = window.onload; 
    if (typeof window.onload != 'function') { 
    window.onload = func; 
    } else { 
    window.onload = function() { 
     if (prevOnLoad) { 
     prevOnLoad(); 
     } 
     func(); 
    } 
    } 
} 

function loadFile(id, filename) { 
    var xmlhttp; 
    if (window.XMLHttpRequest) { 
    xmlhttp=new XMLHttpRequest(); 
    } 
    xmlhttp.onreadystatechange=function() { 
    if (xmlhttp.readyState==4 && xmlhttp.status==200) { 
     document.getElementById(id).innerHTML=xmlhttp.responseText; 
    } 
    } 
    xmlhttp.open('GET', filename, true); 
    xmlhttp.send(); 
} 

addLoadEvent(loadFile('nav', 'nav.txt')); 
addLoadEvent(loadFile('footer', 'footer.txt')); 

function getURLParameter(name) { 
    return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null; 
} 
+1

'addLoadEvent (loadFile ('nav', 'nav.txt'));' не делает то, что, по вашему мнению, делает. – zzzzBov

+0

Аргумент 'addLoadEvent' должен быть функцией, а не вызовом функции. – Barmar

+0

Не могли бы вы прояснить эти комментарии? Если он не делает то, что я думаю, что он делает, как он все еще работает в большинстве мест? Барнар, вы указываете, что я отправляю неверные параметры в addLoadEvent, но почему-то все еще работает в большинстве случаев? Если бы параметры были неправильного типа, не было бы ошибкой 100%? – Doug

ответ

1

Аргумент addLoadEvent должен быть функцией, которая будет вызываться во время onload обратного вызова. Вы вызываете функцию немедленно и передаете ее возвращаемое значение, поэтому функция не ждет события onload, и вы получаете ошибки, потому что элементы еще не находятся в DOM. Оно должно быть:

addLoadEvent(function() { loadFile('nav', 'nav.txt'); }); 
addLoadEvent(function() { loadFile('footer', 'footer.txt'); }); 
addLoadEvent(initialFighter); 

Вам не нужно анонимная функция-обертки для initialFighter, так как он не принимает никаких аргументов. Вам просто нужно оставить (), поэтому вы передаете ссылку на функцию, а не сразу вызываете функцию.

Кроме того, вместо цепочки onload обработчиков событий, сохраняя старое значение и называя его внутри новой функции, вы можете просто использовать addEventListener, так как они автоматически добавлять в список слушателей, вместо того, чтобы заменить его:

function addLoadEvent(func) { 
    window.addEventListener("load", func); 
} 
+0

интересный. Объяснение имеет смысл, и я попытаюсь его реализовать, но я все еще не могу понять, как эти 2 вызова loadFile работают, если они не были поставлены в очередь. Если они не были поставлены в очередь, эти вызовы явно происходили до существования элементов, которые они должны были модифицировать, что также должно было привести к их провалу? Oops edit, для части ответа 2, мне нужно будет изучить addEventListener, я не знаю, как это связано с window.onload. – Doug

+0

Если вы поместите его в положение два, 'loadFile ('nav', 'nav.txt')' должен работать, но 'loadFile ('footer', 'footer.txt')' должен выйти из строя, потому что местоположение два после Загружается элемент 'nav'. Вызов 'loadFile' не поставлен в очередь, это происходит немедленно. – Barmar

+0

'initialFighter()' работает в теле, потому что после загрузки элемента 'picture'. – Barmar

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

  • Нет связанных вопросов^_^