вставьте тег сценария с удаленным src и дождитесь его выполнения - PullRequest
57 голосов
/ 20 декабря 2011

Как я могу вставить элемент <script src="https://remote.com/"></script> на мою страницу, дождаться его выполнения и затем использовать функции, которые он определяет?

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

Изменить для дополнительной информации: у меня нет доступа к удаленному сценарию.

Ответы [ 6 ]

117 голосов
/ 20 декабря 2011

Вы можете использовать Google Analytics или Facebook метод:

(function(d, script) {
    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function(){
        // remote script has loaded
    };
    script.src = 'http://www.google-analytics.com/ga.js';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));

ОБНОВЛЕНИЕ:

Ниже представлен новый метод Facebook; он опирается на существующий тег сценария вместо <head>:

(function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)){ return; }
    js = d.createElement(s); js.id = id;
    js.onload = function(){
        // remote script has loaded
    };
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
  • Замените facebook-jssdk вашим уникальным идентификатором скрипта, чтобы избежать его добавления более одного раза.
  • Замените URL скрипта своим собственным.
30 голосов
/ 18 августа 2016

Тот же метод с использованием прослушивателей событий и конструкций ES2015:

function injectScript(src) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.async = true;
        script.src = src;
        script.addEventListener('load', resolve);
        script.addEventListener('error', () => reject('Error loading script.'));
        script.addEventListener('abort', () => reject('Script loading aborted.'));
        document.head.appendChild(script);
    });
}

injectScript('http://example.com/script.js')
    .then(() => {
        console.log('Script loaded!');
    }).catch(error => {
        console.log(error);
    });
9 голосов
/ 11 июля 2017

Это один из способов динамической загрузки и одновременного выполнения списка скриптов.Вам нужно вставить каждый тег сценария в DOM, явно установив для его атрибута async значение false:

script.async = false;

Скрипты, которые были внедрены в DOM, по умолчанию выполняются асинхронно, поэтому необходимо установить атрибут asyncв false вручную, чтобы обойти это.

Пример

<script>
(function() {
  var scriptNames = [
    "https://code.jquery.com/jquery.min.js",
    "example.js"
  ];
  for (var i = 0; i < scriptNames.length; i++) {
    var script = document.createElement('script');
    script.src = scriptNames[i];
    script.async = false; // This is required for synchronous execution
    document.head.appendChild(script);
  }
  // jquery.min.js and example.js will be run in order and synchronously
})();
</script>

<!-- Gotcha: these two script tags may still be run before `jquery.min.js`
     and `example.js` -->
<script src="example2.js"></script>
<script>/* ... */<script>

Ссылки

6 голосов
/ 20 декабря 2011

что-то вроде этого должно сработать:

(function() {
    // Create a new script node
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.onload = function() {
        // Cleanup onload handler
        script.onload = null;

        // do stuff with the loaded script!

    }

    // Add the script to the DOM
    (document.getElementsByTagName( "head" )[ 0 ]).appendChild( script );

    // Set the `src` to begin transport
    script.src = "https://remote.com/";
})();

надеюсь, это поможет! веселит.

2 голосов
/ 03 августа 2018

Динамический import()

Используя динамический импорт, вы можете теперь загружать модули и ждать их выполнения, просто так:

import("http://example.com/module.js").then(function(module) {
  alert("module ready");
});

Если модуль уже был загружени выполняется, он не будет загружен и выполнен снова, но обещание, возвращаемое import, все равно разрешится.

Обратите внимание, что файл загружается как модуль, а не как скрипт.Модули выполняются в строгом режиме и загружаются в области видимости модуля, что означает, что переменные не становятся автоматически глобальными, как в обычно загружаемых скриптах.Используйте ключевое слово export в модуле, чтобы поделиться переменной с другими модулями или сценариями.

Ссылки:

0 голосов
/ 09 апреля 2019

Создать загрузчик

Вы можете внедрить скрипт в упорядоченным образом в загрузчике.

Помните, что выполнение динамически загружаемых сценариев обычно происходит после статически загруженных сценариев (т. Е. <script src="My_script.js"></script>) (порядок внедрения в DOM не гарантирует обратного):

например, loader.js:

function appendScript(url){
   let script = document.createElement("script");
   script.src = url;
   script.async = false //IMPORTANT
   /*Node Insertion Point*/.appendChild(script);
}
appendScript("my_script1.js");
appendScript("my_script2.js");

my_script1.js будет эффективно выполняться до my_script2.js, (полезно, если зависимости my_script2.js находятся в my_script1.js)

Обратите внимание, что важно иметь script.async = false, поскольку динамически загружаемые скрипты по умолчанию имеют async = true, async не гарантирует вам порядок загрузки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...