Подтвердить что ты не робот

Вставьте тег script с удаленным src и дождитесь его выполнения

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

FYI: В моем случае script будет обрабатывать некоторые кредитные карты в редких случаях, поэтому я не хочу включать его всегда. Я хочу включить его быстро, когда пользователь откроет диалог change-credit-card-options, а затем отправьте ему новые параметры кредитной карты.

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

4b9b3361

Ответ 1

Вы можете использовать метод 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; он полагается на существующий тег script вместо <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 своим уникальным идентификатором script, чтобы избежать его добавления более одного раза.
  • Замените URL-адрес script своим.

Ответ 2

Тот же метод с использованием прослушивателей событий и конструкций 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);
    });

Ответ 3

Это один из способов динамически загружать и выполнять список сценариев синхронно. Вам нужно вставить каждый тег сценария в 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>

Ссылки

Ответ 4

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

(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/";
})();

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

Ответ 5

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

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

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

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

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

Ссылки:

Ответ 6

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

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

Помните, что выполнение динамически загружаемых сценариев обычно происходит после статически загружаемых сценариев (т.е. <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 не гарантирует вам порядок загрузки.

Ответ 7

Вот моя адаптированная версия, основанная на ответе Фрэнка:

static async importScript(src, expressionToEvaluateAndReturn){

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.async = true;
            script.src = src;
            script.addEventListener('load', (event)=>{
                if(expressionToEvaluateAndReturn){
                    try{
                        let result = eval(expressionToEvaluateAndReturn);
                        resolve(result);
                    } catch(error){
                        reject(error);
                    }

                } else {
                    resolve();
                }
            });
            script.addEventListener('error', () => reject('Error loading script "' + src + '"'));
            script.addEventListener('abort', () => reject('Script loading aborted for "' + src + '"'));
            document.head.appendChild(script);
        });    

    }   

Пример использования:

let d3 = await importScript('/bower_components/d3/d32.min.js','d3')
                    .catch(error => {
                        console.log(error);
                        throw error;
                    });