Вставьте тег script с удаленным src и дождитесь его выполнения
Как я могу вставить элемент <script src="https://remote.com/"></script>
на свою страницу, дождаться его выполнения, а затем использовать функции, которые он определяет?
FYI: В моем случае script будет обрабатывать некоторые кредитные карты в редких случаях, поэтому я не хочу включать его всегда. Я хочу включить его быстро, когда пользователь откроет диалог change-credit-card-options, а затем отправьте ему новые параметры кредитной карты.
Изменить для дополнительной информации: у меня нет доступа к удаленному script.
Ответы
Ответ 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;
});