Каков наилучший способ загрузки файла javascript динамически? (с ajax или тегом сценария импорта или другим способом) [duplicate]

  UPDATE [table_name] AS T1, (SELECT [имя_столбца] FROM [имя_таблицы] WHERE [имя_столбца] = [значение]) AS T2 SET T1. [column_name] = T2. [column_name] + 1 WHERE T1.  [column_name] = [значение];   
99
задан Benjamin 18 November 2013 в 21:02
поделиться

19 ответов

Пара решений для загрузки async:

//this function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
  var s,
      r,
      t;
  r = false;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = src;
  s.onload = s.onreadystatechange = function() {
    //console.log( this.readyState ); //uncomment this line to see which ready states are called.
    if ( !r && (!this.readyState || this.readyState == 'complete') )
    {
      r = true;
      callback();
    }
  };
  t = document.getElementsByTagName('script')[0];
  t.parentNode.insertBefore(s, t);
}

Если у вас уже есть jQuery на странице, просто используйте:

$.getScript(url, successCallback) *

Кроме того, возможно, что ваши сценарии загружаются / выполняются до того, как документ будет загружен, что означает, что вам нужно будет ждать document.ready до того, как события будут привязаны к элементам.

Невозможно точно рассказать, какова ваша проблема, не видя кода.

Самое простое решение - сохранить все ваши скрипты в нижней части страницы, Не блокируйте загрузку содержимого HTML во время их выполнения. Это также позволяет избежать необходимости асинхронной загрузки каждого требуемого сценария.

Если у вас особенно причудливое взаимодействие, которое не всегда используется, для чего требуется большой скрипт какого-либо типа, было бы полезно избежать загрузки этот сценарий пока не понадобится (ленивая загрузка).

* скрипты, загруженные с помощью $.getScript, скорее всего, не будут кэшироваться


Для всех, кто может использовать современные функции, такие как объект Promise , функция loadScript стала значительно проще:

function loadScript(src) {
    return new Promise(function (resolve, reject) {
        var s;
        s = document.createElement('script');
        s.src = src;
        s.onload = resolve;
        s.onerror = reject;
        document.head.appendChild(s);
    });
}

Имейте в виду, что эта версия больше не принимает callback, поскольку возвращенное обещание будет обрабатывать обратный вызов. Теперь было бы loadScript(src, callback) loadScript(src).then(callback).

У этого есть дополнительный бонус, позволяющий обнаруживать и обрабатывать сбои, например, можно вызвать ...

loadScript(cdnSource)
    .catch(loadScript.bind(null, localSource))
    .then(successCallback, failureCallback);
]

... и будет обрабатывать изъяны CDN изящно.

144
ответ дан zzzzBov 15 August 2018 в 21:13
поделиться
  • 1
    Я вот-вот начну пробовать это. но если я загружу эти сценарии на другой странице, когда перенаправляю страницу на другую страницу, и на этой странице есть те же сценарии, что они не должны тратить время на загрузку. они должны быть в кеше правильно? так что я должен использовать эту технику вместо этого? – Tono Nam 10 October 2011 в 23:07
  • 2
    Я изменил и добавил ребенка к тегу head вместо тела ... ..var x = document.getElementsByTagName ('head') [0]; x.appendChild (ы); – Tono Nam 10 October 2011 в 23:25
  • 3
    @TonoNam, вы можете просто использовать document.head.appendChild, однако есть некоторые проблемы с нишей с добавлением скриптов к <head>; ничего, что помешало бы загрузке и выполнению сценариев. – zzzzBov 12 October 2011 в 18:38
  • 4
    Мне пришлось использовать t.parentNode.insertBefore (в отличие от t.parent). – Phil LaNasa 23 December 2013 в 23:33
  • 5
    @MuhammadUmer, если вы пишете дополнительный скриптовый тег с document.write до загрузки документа, сценарий будет выполняться синхронно как часть загрузки страницы и не будет включать асинхронное поведение обратного вызова сам по себе. Если вы создаете элемент сценария и добавляете его на страницу, у вас будет доступ к добавлению прослушивателей событий для асинхронного запуска. tl; dr: зависит от того, как вы загружаете скрипт с помощью JS. – zzzzBov 30 October 2014 в 02:20

Ну, x.parentNode возвращает элемент HEAD, поэтому вы вставляете скрипт непосредственно перед тегом head. Возможно, это проблема.

Вместо этого попробуйте x.parentNode.appendChild().

0
ответ дан alekop 15 August 2018 в 21:13
поделиться

Вот отличное современное решение для загрузки асинхронного скрипта, хотя оно адресовано только сценарию js с асинхронным ложным.

Существует большая статья, написанная на www.html5rocks.com - Глубокое погружение в мутные воды загрузки скрипта .

После рассмотрения многих возможных решений, автор пришел к выводу, что добавление js-скриптов в конец элемента body является наилучшим способом избежать блокировки отображения страницы с помощью js-скриптов.

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

Учитывая, что у вас есть четыре сценария с именем script1.js, script2.js, script3.js, script4.js, вы можете сделать это с помощью async = false:

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

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

Firefox & lt; 3.6, Opera говорит: я понятия не имею, что это за «асинхронная» вещь, но это так происходит. Я запускаю скрипты, добавленные через JS, в том порядке, в котором они добавлены.

Safari 5.0 говорит: «Я понимаю», async ", но не понимают, что он устанавливает значение" false "с помощью JS. Я буду выполнять ваши скрипты, как только они приземлятся, в любом порядке.

IE & lt; 10 говорит: «Не знаю, как« асинхронно », но есть обходное решение, использующее« onreadystatechange ».

Все остальное говорит:« Я твой друг, мы сделаем это по книге ».

Теперь полный код с IE & lt; 10:

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && ( pendingScripts[0].readyState == 'loaded' || pendingScripts[0].readyState == 'complete' ) ) {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}
1
ответ дан asmmahmud 15 August 2018 в 21:13
поделиться

Несколько примечаний:

  • s.async = true не очень корректно относится к HTML-типу HTML5, верно s.async = 'async' (фактически использование true является правильным, благодаря amn , которые указали это в комментарии ниже чуть ниже)
  • Использование тайм-аутов для управления порядком не очень хорошо и безопасно, и вы также увеличиваете время загрузки, сумма всех тайм-аутов!

Поскольку существует новая причина для загрузки файлов асинхронно, но в порядке, я бы рекомендовал немного более функционально-ориентированный путь по вашему примеру (удалите console.log для использования в производстве :)):

(function() {
    var prot = ("https:"===document.location.protocol?"https://":"http://");

    var scripts = [
        "path/to/first.js",
        "path/to/second.js",
        "path/to/third.js"
    ];

    function completed() { console.log('completed'); }  // FIXME: remove logs

    function checkStateAndCall(path, callback) {
        var _success = false;
        return function() {
            if (!_success && (!this.readyState || (this.readyState == 'complete'))) {
                _success = true;
                console.log(path, 'is ready'); // FIXME: remove logs
                callback();
            }
        };
    }

    function asyncLoadScripts(files) {
        function loadNext() { // chain element
            if (!files.length) completed();
            var path = files.shift();
            var scriptElm = document.createElement('script');
            scriptElm.type = 'text/javascript';
            scriptElm.async = true;
            scriptElm.src = prot+path;
            scriptElm.onload = scriptElm.onreadystatechange = \
                checkStateAndCall(path, loadNext); // load next file in chain when
                                                   // this one will be ready 
            var headElm = document.head || document.getElementsByTagName('head')[0];
            headElm.appendChild(scriptElm);
        }
        loadNext(); // start a chain
    }

    asyncLoadScripts(scripts);
})();
6
ответ дан Community 15 August 2018 в 21:13
поделиться
  • 1
    s.async = true правильный . Свойство async указано явно как логическое выражение в рекомендации W3C по HTML 5 в w3.org/TR/html5/scripting-1.html#attr-script-async . Вы сбиваете с толку атрибут async с свойством async, отображаемым объектами, реализующими интерфейс DOM HTMLScriptElement. В самом деле, при манипулировании соответствующим атрибутом элемента через что-то вроде Element.setAttribute, вы должны использовать element.setAttribute("async", "async"), поскольку все атрибуты HTML являются в первую очередь текстом. – amn 28 June 2016 в 00:17
  • 2
    «Поскольку существует некоторая причина для загрузки файлов асинхронно, но по порядку я рекомендую немного более функциональный путь по вашему примеру [...]». Я знаю, что async обычно «лучше», но что «последнее» на что вы ссылаетесь? – BluE 27 February 2018 в 12:37

Вот мое пользовательское решение для устранения JavaScript-рендеринга:

// put all your JS files here, in correct order
const libs = {
  "jquery": "https://code.jquery.com/jquery-2.1.4.min.js",
  "bxSlider": "https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.5/jquery.bxslider.min.js",
  "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.2/angular.min.js",
  "ngAnimate": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular-animate.min.js"
}
const loadedLibs = {}
let counter = 0

const loadAsync = function(lib) {
  var http = new XMLHttpRequest()
  http.open("GET", libs[lib], true)
  http.onload = () => {
    loadedLibs[lib] = http.responseText
    if (++counter == Object.keys(libs).length) startScripts()
  }
  http.send()
}

const startScripts = function() {
  for (var lib in libs) eval(loadedLibs[lib])
  console.log("allLoaded")
}

for (var lib in libs) loadAsync(lib)

Короче говоря, он асинхронно загружает все ваши сценарии, а затем выполняет их соответственно.

Github repo : https://github.com/mudroljub/js-async-loader

0
ответ дан Damjan Pavlica 15 August 2018 в 21:13
поделиться
  • 1
    Не работает No 'Access-Control-Allow-Origin' header is present on the requested resource – Abram 7 March 2016 в 23:22
  • 2
    Это проблема CORS. [Д0] stackoverflow.com/questions/20035101/… – Damjan Pavlica 21 December 2017 в 23:59

Новый атрибут «async» HTML5 должен сделать трюк. «defer» также поддерживается в большинстве браузеров, если вы беспокоитесь об IE.

async - HTML

<script async src="siteScript.js" onload="myInit()"></script>

defer - HTML

<script defer src="siteScript.js" onload="myInit()"></script>

При анализе нового рекламного блока AdSense я заметил атрибут и поиск приведи меня сюда: http://davidwalsh.name/html5-async

23
ответ дан Donald Porter 15 August 2018 в 21:13
поделиться
  • 1
    из моего понимания после прочтения stackoverflow.com/questions/2774373/… , asyn не для загрузки, а для определения, когда запускать javascript. – JackDev 16 September 2013 в 02:52
  • 2
    Атрибут defer заставляет браузер откладывать выполнение сценария до тех пор, пока документ не будет загружен и не обработан и не будет готов к манипулированию. Асинхронный атрибут заставляет браузер запускать сценарий как можно скорее, но не блокировать разбор документа во время загрузки скрипта – shus 25 November 2014 в 09:18
  • 3
    «asyn не для загрузки, а для определения, когда запускать содержащийся в javascript», Это не противоречит; Во всех случаях браузер начнет загрузку сценария как можно скорее. Но без async или defer он будет блокировать рендеринг во время загрузки. Установка async подскажет, чтобы он не блокировал и не запускал сценарий как можно скорее. Установка defer покажет, что он не заблокирован, но подождите, пока сценарий работает , пока страница не будет выполнена. Обычно нет проблем запускать сценарии ASAP, если у них нет зависимостей (например, jQuery). Если один сценарий имеет зависимости от другого, используйте onLoad, чтобы дождаться его. – Stijn de Witt 19 April 2016 в 08:28
  • 4
    @StijndeWitt Что делать, если ни асинхронно, ни отсрочка не указаны? – Mohammed Shareef C 11 November 2016 в 05:44
  • 5
    @MohammedShareefC Если вы не укажете ни одно из них, вы получите что-то очень похожее на поведение синхронизации; браузер блокирует дальнейшую обработку, пока он загружает и запускает сценарий. Так эффективно поведение по умолчанию - это синхронизация. Но поскольку это вредно для производительности, браузеры будут работать вокруг него настолько, насколько это возможно. Они могут продолжать синтаксический анализ, загрузку и применение CSS и т. Д. Однако они не могут запускать следующий фрагмент сценария. Так что материал будет блокироваться. Установив async, вы говорите браузеру, что все в порядке, и вы убедитесь, что вы заставляете его работать самостоятельно. – Stijn de Witt 11 November 2016 в 21:37

Я бы предложил сначала изучить мини-файлы и посмотреть, дает ли это вам достаточно большой прирост скорости. Если ваш хост работает медленно, можно попробовать поставить статический контент на CDN.

-2
ответ дан Jason Miesionczek 15 August 2018 в 21:13
поделиться

Считаете ли вы использование Fetch Injection? Я обработал библиотеку с открытым исходным кодом, названную fetch-inject , чтобы обрабатывать такие случаи. Вот что может выглядеть ваш загрузчик с помощью lib:

fetcInject([
  'js/jquery-1.6.2.min.js',
  'js/marquee.js',
  'css/marquee.css',
  'css/custom-theme/jquery-ui-1.8.16.custom.css',
  'css/main.css'
]).then(() => {
  'js/jquery-ui-1.8.16.custom.min.js',
  'js/farinspace/jquery.imgpreload.min.js'
})

. Для обнаружения функции обратной совместимости и возврата к XHR Injection или Script DOM Elements или просто встраивайте теги в страницу с помощью document.write.

0
ответ дан Josh Habdas 15 August 2018 в 21:13
поделиться

Здесь немного ES6, если кто-то хочет использовать его в React, например

import {uniqueId} from 'lodash' // optional
/**
 * @param {String} file The path of the file you want to load.
 * @param {Function} callback (optional) The function to call when the script loads.
 * @param {String} id (optional) The unique id of the file you want to load.
 */
export const loadAsyncScript = (file, callback, id) => {
  const d = document
  if (!id) { id = uniqueId('async_script') } // optional
  if (!d.getElementById(id)) {
    const tag = 'script'
    let newScript = d.createElement(tag)
    let firstScript = d.getElementsByTagName(tag)[0]
    newScript.id = id
    newScript.async = true
    newScript.src = file
    if (callback) {
      // IE support
      newScript.onreadystatechange = () => {
        if (newScript.readyState === 'loaded' || newScript.readyState === 'complete') {
          newScript.onreadystatechange = null
          callback(file)
        }
      }
      // Other (non-IE) browsers support
      newScript.onload = () => {
        callback(file)
      }
    }
    firstScript.parentNode.insertBefore(newScript, firstScript)
  } else {
    console.error(`The script with id ${id} is already loaded`)
  }
}

0
ответ дан JoxieMedina 15 August 2018 в 21:13
поделиться

Пример из google

<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script>
6
ответ дан kleopatra 15 August 2018 в 21:13
поделиться

Благодаря HTML5 вы можете теперь объявить сценарии, которые вы хотите загрузить асинхронно, добавив в тег «async»:

<script async>...</script>

Примечание. Асинхронный атрибут предназначен только для внешних скриптов (и должен использоваться только в том случае, если присутствует атрибут src).

Примечание. Существует несколько способов выполнения внешнего скрипта:

  • Если присутствует async: сценарий выполняется асинхронно с остальной частью страницы (сценарий будет выполнен, пока страница продолжит разбор)
  • Если async отсутствует и присутствует отложенный сценарий: сценарий выполняется, когда страница закончила синтаксический анализ
  • Если не присутствуют ни асинхронные, ни отсрочки: сценарий извлекается и выполняется немедленно, прежде чем браузер продолжит разбор страницы

См. это: http: // www .w3schools.com / теги / att_script_async.asp

1
ответ дан odroz 15 August 2018 в 21:13
поделиться
  • 1
    Пожалуйста, не используйте w3schools в качестве учебного материала. – tereško 4 December 2017 в 21:32

Вы можете использовать LABJS или RequreJS

Скриптовые загрузчики, такие как LABJS, RequireJS, улучшат скорость и качество вашего кода.

0
ответ дан shA.t 15 August 2018 в 21:13
поделиться

Я бы предложил вам взглянуть на Modernizr . Это небольшая небольшая библиотека, в которую вы можете асинхронно загружать свой javascript с функциями, которые позволяют вам проверить, загружен ли файл, и выполнить сценарий в другом, указанном вами.

Вот пример загрузки jquery:

Modernizr.load([
  {
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
    complete: function () {
      if ( !window.jQuery ) {
            Modernizr.load('js/libs/jquery-1.6.1.min.js');
      }
    }
  },
  {
    // This will wait for the fallback to load and
    // execute if it needs to.
    load: 'needs-jQuery.js'
  }
]);
1
ответ дан Shawn Mclean 15 August 2018 в 21:13
поделиться

Проверьте этот https://github.com/stephen-lazarionok/async-resource-loader . В нем есть пример, который показывает, как загрузить JS, CSS и несколько файлов одним выстрелом.

0
ответ дан Stephen L. 15 August 2018 в 21:13
поделиться
  • 1
    Требуется jquery ... – Abram 7 March 2016 в 23:23
  • 2
    Его можно немного изменить, чтобы избавиться от зависимости jquery – Stephen L. 29 March 2016 в 07:26

Вы можете найти эту статью в вики интересной: http://ajaxpatterns.org/On-Demand_Javascript

В ней объясняется, как и когда использовать такую ​​технику.

1
ответ дан tereško 15 August 2018 в 21:13
поделиться
  • 1
    К сожалению, ссылка, похоже, мертва. :( – Eric Seastrand 4 December 2017 в 21:28
  • 2
    @Эрик это потому, что это древний метод динамического погрузки кода: D – tereško 4 December 2017 в 21:31

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

callMyFunctions();

вместо:

$(window).load(function() {
      callMyFunctions();
});

Этот второй бит скрипта ждет, пока браузер полностью не загрузит весь ваш код Javascript до того, как он начнет выполнение каких-либо из ваших сценариев, что приведет к тому, что пользователь будет загружен быстрее.

вы хотите улучшить пользовательский опыт, уменьшив время загрузки, я бы не пошел на опцию «загрузка экрана». По-моему, это было бы гораздо более раздражающим, чем просто медленная загрузка страницы.

1
ответ дан therin 15 August 2018 в 21:13
поделиться

Я бы выполнил ответ zzzzBov с проверкой наличия обратного вызова и разрешить передачу аргументов:

    function loadScript(src, callback, args) {
      var s, r, t;
      r = false;
      s = document.createElement('script');
      s.type = 'text/javascript';
      s.src = src;
      if (typeof(callback) === 'function') {
        s.onload = s.onreadystatechange = function() {
          if (!r && (!this.readyState || this.readyState === 'complete')) {
            r = true;
            callback.apply(args);
          }
        };
      };
      t = document.getElementsByTagName('script')[0];
      t.parent.insertBefore(s, t);
    }
2
ответ дан Tibo 15 August 2018 в 21:13
поделиться

Я загрузил скрипты асинхронно (html 5 имеет эту функцию), когда все сценарии, где была сделана загрузка, я перенаправил страницу в index2.html, где index2.html использует те же библиотеки. Поскольку браузеры имеют кеш, когда страница перенаправляется на index2.html, index2.html загружается менее чем за секунду, потому что у нее есть все необходимое для загрузки страницы. На моей странице index.html я также загружаю изображения, которые планирую использовать, чтобы браузер размещал эти изображения в кеше. поэтому мой index.html выглядит так:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Project Management</title>

    <!-- the purpose of this page is to load all the scripts on the browsers cache so that pages can load fast from now on -->

    <script type="text/javascript">

        function stylesheet(url) {
            var s = document.createElement('link');
            s.type = 'text/css';
            s.async = true;
            s.src = url;
            var x = document.getElementsByTagName('head')[0];
            x.appendChild(s);
        }

        function script(url) {
            var s = document.createElement('script');
            s.type = 'text/javascript';
            s.async = true;
            s.src = url;
            var x = document.getElementsByTagName('head')[0];
            x.appendChild(s);
        }

        //load scritps to the catche of browser
        (function () {            
                stylesheet('css/custom-theme/jquery-ui-1.8.16.custom.css');
                stylesheet('css/main.css');
                stylesheet('css/marquee.css');
                stylesheet('css/mainTable.css');

                script('js/jquery-ui-1.8.16.custom.min.js');
                script('js/jquery-1.6.2.min.js');
                script('js/myFunctions.js');
                script('js/farinspace/jquery.imgpreload.min.js');
                script('js/marquee.js');            
        })();

    </script>

    <script type="text/javascript">
       // once the page is loaded go to index2.html
        window.onload = function () {
            document.location = "index2.html";
        }
    </script>

</head>
<body>

<div id="cover" style="position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:Black; z-index:100;">Loading</div>

<img src="images/home/background.png" />
<img src="images/home/3.png"/>
<img src="images/home/6.jpg"/>
<img src="images/home/4.png"/>
<img src="images/home/5.png"/>
<img src="images/home/8.jpg"/>
<img src="images/home/9.jpg"/>
<img src="images/logo.png"/>
<img src="images/logo.png"/>
<img src="images/theme/contentBorder.png"/>

</body>
</html>

еще одна приятная вещь в том, что я могу разместить загрузчик на странице, и когда страница будет сделана, загрузка загрузчика исчезнет и в матах миллисекунды новая страница будет запущена.

8
ответ дан Tono Nam 15 August 2018 в 21:13
поделиться
  • 1
    и один не может продолжать задаваться вопросом, насколько низкий ваш пейджер. – Dementic 21 September 2013 в 15:42
  • 2
    @Dementic Вы имеете в виду метатеги? – Mohammed Shareef C 11 November 2016 в 05:44
  • 3
    @MohammedShareefC Ирония. Специальная страница, предназначенная для предварительной загрузки, не похожа на хорошую идею SEO. Предварительная загрузка отличная, но вам не нужно перенаправлять ее. Просто придерживайтесь ссылок в скрытом div, и браузер автоматически позаботится об этом для вас. Затем не перенаправляйте, а просто показывайте фактическую страницу. COPY-PASTERS READ THIS : Пожалуйста, измените кодировку ISO-88591 на UTF-8, прежде чем использовать какой-либо из этих HTML-файлов, чтобы остальные из нас могли в ближайшее время выйти из кодирования. Благодаря! – Stijn de Witt 11 November 2016 в 21:43
  • 4
    Посмотрите мой новый ответ: stackoverflow.com/questions/7718935/load-scripts-asynchronously/… – asmmahmud 3 August 2017 в 16:51

Я написал небольшое сообщение, чтобы помочь с этим, вы можете прочитать здесь https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ , но я добавил вспомогательный класс ниже. Он будет автоматически ждать загрузки сценария и возврата указанного атрибута окна.

export default class ScriptLoader {
  constructor (options) {
    const { src, global, protocol = document.location.protocol } = options
    this.src = src
    this.global = global
    this.protocol = protocol
    this.isLoaded = false
  }

  loadScript () {
    return new Promise((resolve, reject) => {
      // Create script element and set attributes
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.async = true
      script.src = `${this.protocol}//${this.src}`

      // Append the script to the DOM
      const el = document.getElementsByTagName('script')[0]
      el.parentNode.insertBefore(script, el)

      // Resolve the promise once the script is loaded
      script.addEventListener('load', () => {
        this.isLoaded = true
        resolve(script)
      })

      // Catch any errors while loading the script
      script.addEventListener('error', () => {
        reject(new Error(`${this.src} failed to load.`))
      })
    })
  }

  load () {
    return new Promise(async (resolve, reject) => {
      if (!this.isLoaded) {
        try {
          await this.loadScript()
          resolve(window[this.global])
        } catch (e) {
          reject(e)
        }
      } else {
        resolve(window[this.global])
      }
    })
  }
}

Использование выглядит так:

const loader = new Loader({
    src: 'cdn.segment.com/analytics.js',
    global: 'Segment',
})

// scriptToLoad will now be a reference to `window.Segment`
const scriptToLoad = await loader.load()
0
ответ дан Zach 15 August 2018 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: