Загрузка тяжелых js-виджетов, вызывающих зависание браузера

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

function setWidgets(){
  var div = document.getElementById("content");
  var subDiv = div.getElementsByTagName('div');
  var id;
  var arr = [];

  for(var i = 0; i < subDiv.length; i++) {
    var elem = subDiv[i];
    if(elem.className == "info" ) {
      setTimeout( setWidget(elem) , 600);
    }
  }
}

function setWidget(elem) { 
  var para = elem.innerHTML.split(",");
  var divId = para[2];
  var widget = getWidget(para);
  var elemnt = document.getElementById(divId);

  $(elemnt).html(widget);
}

function getWidget(para){

  var pair = para[0];
  var frame = para[1];
  var elemId = para[2];
  var widget = [];

  widget.push(
    '<script>',
    '\n',
    "new TradingView.widget({",
    '\n',
    '"width": 512,',
    '\n',
    '"height": 288,',
    '\n',
    '"symbol": "FX:',
    pair,
    '",',
    '\n',
    '"interval":',
    '"',
    frame,
    '",',
    '\n',
    '"container_id": ',
    '"',
    elemId,
    '",',
    '\n',
    '"timezone": "exchange",',
    '\n',
    '"theme": "White",',
    '\n',
    '"style": "1",',
    '\n',
    '"toolbar_bg": "#f1f3f6",',
    '\n',
    '"hide_top_toolbar": true,',
    '\n',
    '"save_image": false,',
    '\n',
    '"hideideas": true',
    '\n',
    '});',
    '\n',
    '</',
    'script>'
  );

  return widget.join("");
}

1 ответ

Решение

Проблема здесь:

setTimeout( setWidget(elem) , 600);

Ты звонишь setWidget с Elem и передать результат в setTimeout, Вам нужно передать функцию setTimeout и он позвонит после задержки:

setTimeout(function (elem) {
    setWidget(elem) 
}.bind(null, elem), 600);

Но в этом случае вы начнете все setTimeout Сразу нужно сделать задержку разной:

setTimeout(function (elem) {
    setWidget(elem) 
}.bind(null, elem), 600 * (i + 1));

Примечание: также вам нужно создать область с текущим elem , я использую Function.prototype.bind для этого. Если вам нужна поддержка IE6-8, вы можете использовать $.proxy или создайте обертку IIFE:

  //create IIFE (Immediately Invoked Function Expression) wrapper
  //IIFE will create a new scope with needed variable elem
  setTimeout((function (elem) {
    return function () {
       setWidget(elem)
    }
  }(elem)), 600 * (i + 1));
Другие вопросы по тегам