Как выполнить скрипт по окончании его вставки через document.head.appendChild(my_script)?

У меня возникла вот такая трудность.

Я пользуюсь загрузкой скрипта (и добавлением его на страницу) при помощи такого кода:

    var my_script = document.createElement('script');
    my_script.setAttribute('type','text/javascript');
    my_script.setAttribute('src','https://mysite.ru/storage/script.js');
    document.head.appendChild(my_script);
    function_onload();

При этом последня строка function_onload() - это вызов функции, которая уже находится в загруженном скрипте. И на этой строке я получаю ошибку

    polyfills-es5.js:1 Uncaught ReferenceError: function_onload is not defined

Ну, понятно.

Операция добавления скрипта ( document.head.appendChild(my_script) ) - асинхронная, и в тот момент, когда я вызываю функцию function_onload - она еще не завершилась.

я пробовал разные подходы:

писал

    my_script.async = false;

до вызова my_script.setAttribute, ( это ни на что не повлияло )

пробовал переписать последнюю строку в стиле

    document.head.appendChild(my_script)
    .then ( () => function_onload() );

При этом я получил другую ошибку - TypeError: document.head.appendChild(...).then is not a function

Можно, конечно, "завести будильник" (поставить таймер), но это очень ненадёжное решение...

Что можно сделать в такой ситуации? как понять, что скрипт уже загрузился и готов к выполнению?

Спасибо.


Ответы (2 шт):

Автор решения: ksa

Что можно сделать в такой ситуации? как понять, что скрипт уже загрузился и готов к выполнению?

У самого элемента document.createElement('script') есть событие load. Оно "срабатывает" как раз после загрузки скрипта.

Все что тебе остается - навесить обработчик, который и вызовет (уже загруженную) функцию. Что-то типа такого...

my_script.addEventListener('load', _ => function_onload())
→ Ссылка
Автор решения: S.H.

У меня возникло усложнение задачи, которое было связано вот с чем:

в примере, который есть в вопросе (и в ответе) у скрипта есть атрибут 'src'.

И загрузка скрипта происходит с некого URL-адреса.

А когда код будет загружен - то нужно запустить одну из функций внутри этого кода.

И в этом случае для запуска надо использовать событие 'load' и "вешаться" на него с помощью

my_script.addEventListener('load', _ => function_onload());

Но что, если загрузка скрипта из внешнего источника не предполагается?

Оказывется, при этом задача как бы "упрощается", но... событие 'load' больше не работает!

в этом случае все проще:

Пускай у нас есть тело скрипта (в переменной my_script_body). Тогда делаем примерно так:

<html>
<head>
    <script>

    function body_onload(){
        var my_script_body = 'function myScriptFunction(){ alert(\'Hi from myScriptFunction!\'); }';
        var my_script = document.createElement('script');
        my_script.setAttribute('type','text/javascript');
        //my_script.innerText = my_script_body;
        my_script.innerHTML = my_script_body;
        document.head.appendChild(my_script);
        myScriptFunction();
    }

    </script>
</head>
<body onload='body_onload();'>
<h4>
    Это пример, казалось бы, простой функциональности
</h4>
</body>
</html>

Этот пример выводит alert при заходе на страницу. При этом добавление "тела" скрипта происходит my_script.innerText=... или my_script.innerHTML=... , а запуск скрипта происходит "в синхронном стиле", без ожидания какого либо события, вызовом myScriptFunction();

→ Ссылка