Функция Setinterval, повторяющая содержимое HTML

#javascript #setinterval

Вопрос:

У меня есть строка содержимого таблицы, которая извлекается из API, в то время как я использую функцию setinterval, она просто повторяет содержимое обновленной строки таблицы.

Например: (Это пример вывода, а не фактический)

Предположим, что у меня есть контент

 John price 2000
 

По истечении временного интервала в 1 секунду он должен обновить новое значение из API, например

 John price 2200
 

Но что я получаю, так это то, что каждый раз, когда он обновляется, он просто добавляет, как

 John price 2000
John price 2200
John price 2120 ......
 

Мой Код:

     <table class="table">
      <thead class="thead-dark">
        <tr>
          <th>Coin</th>
          <th>Symbol</th>
          <th>Currency</th>
          <th>Price</th>
        </tr>
      </thead>
  <tbody id="details">

  <tbody>
    </table> 
 var data, len, len1, name, symbol, currency, price;

const api_url = "https://api.wazirx.com/api/v2/market-status";

async function get_data_from_api() {

  const response = await fetch(api_url);

  data = await response.json();

  len = Object.keys(data["markets"]).length;
  len1 = Object.keys(data["assets"]).length;

  for (let i = 0; i < len; i  ) {
    for (let j = 0; j < len1; j  ) {
      if (data['markets'][i]['baseMarket'] == data['assets'][j]['type'] amp;amp; data['markets'][i]['quoteMarket'] == "inr") {

        name = data['assets'][j]['name'];
        symbol = data['assets'][j]['type'];
        currency = data['markets'][i]['quoteMarket'];
        price = data['markets'][i]['buy'];
        document.getElementById('details').innerHTML  = "<tr><td>"   name   "</td><td>"   symbol   "</td><td>"   currency   "</td><td>"   price   "</td></tr>";
      }
    }
  }
}

get_data_from_api();

setInterval(get_data_from_api, 1000); 

Комментарии:

1. = объединяет

2. Просто замените = на = в вашем внутреннем htmlе?

3. попробовал это, но если я удалю =, это означает, что на моем столе ничего не отображается, это просто пустой идентификатор, в чем проблема. но если я использую =, это означает, что вывод отображается правильно.

4. @Браво, я только что ответил на вопрос, это должно сработать.

5. Я думаю, что если вы приведете пример данных, полученных из вашего API. Это поможет людям понять ваш вопрос и легко дать на него ответ.

Ответ №1:

Помимо принятого ответа. Я также рекомендую вам использовать цикл while с wait функцией ниже вместо setInterval .

setInterval может вызывать API без необходимости. Например. при первом вызове api api требуется одна секунда для ответа, в то же время вы вызываете api во второй раз, когда он отвечает всего за 100 мс, и на самом деле вы не увидите результат первого раза, потому что второй вызов немедленно обновляет первый вызов.

 const api_url = "https://api.wazirx.com/api/v2/market-status";

const wait = ms => new Promise(res => setTimeout(res, ms));

(async function run() {
  while (true) {
    try {
      const response = await fetch(api_url);
      const data = await response.json();
      //html jobs.....
      await wait(1000);
    } catch (err) {
      console.log(err);
      continue;
    }
  }
})();
 

Комментарии:

1. почему? Я имею в виду, конечно, это не заблокирует основную нить или что-то в этом роде … но… почему? в чем преимущество

2. @Bravo, setInterval может вызывать API без необходимости. Например. при первом вызове api api требуется одна секунда для ответа, в то же время вы вызываете api во второй раз, когда он отвечает всего за 100 мс, и на самом деле вы не увидите результат первого раза, потому что второй вызов немедленно обновляет первый вызов.

3. Это вполне логично — я задавался вопросом, а не критиковал

4. @Браво, конечно, мы просто обсуждаем.

5. хотя… вы могли бы сделать то же самое с setTimeout

Ответ №2:

Вы просто добавляете содержимое в узел с помощью

 document.getElementById('details').innerHTML  = "<tr><td>" name "</td><td>" symbol "</td><td>" currency "</td><td>" price "</td></tr>";
 

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

 document.getElementById('details').innerHTML = "";
 

Если есть только один узел, удовлетворяющий условию, просто назначьте значение с

 document.getElementById('details').innerHTML = "<tr><td>" name "</td><td>" symbol "</td><td>" currency "</td><td>" price "</td></tr>";
 

Рабочее решение будет примерно таким.

 var data, len, len1, name, symbol, currency, price;

const api_url = "https://api.wazirx.com/api/v2/market-status";

async function get_data_from_api() {

  const response = await fetch(api_url);

  document.getElementById('details').innerHTML = '';

  data = await response.json();

  len = Object.keys(data["markets"]).length;
  len1 = Object.keys(data["assets"]).length;

  for (let i = 0; i < len; i  ) {
    for (let j = 0; j < len1; j  ) {
      if (data['markets'][i]['baseMarket'] == data['assets'][j]['type'] amp;amp; data['markets'][i]['quoteMarket'] == "inr") {

        name = data['assets'][j]['name'];
        symbol = data['assets'][j]['type'];
        currency = data['markets'][i]['quoteMarket'];
        price = data['markets'][i]['buy'];
        document.getElementById('details').innerHTML  = "<tr><td>"   name   "</td><td>"   symbol   "</td><td>"   currency   "</td><td>"   price   "</td></tr>";
      }
    }
  }
}

get_data_from_api();

setInterval(get_data_from_api, 1000);
 

Комментарии:

1. @Nitheesh да, но у меня есть несколько данных, поступающих из моего API с помощью forloop, поэтому я не могу поставить ‘=’

2. Браво, я не проверил твой ответ, он был удален b4, я в него вхожу

3. есть ли какая-либо возможность обратиться только к деталям цены? В настоящее время все это освежает. Есть идеи ?

Ответ №3:

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

 document.getElementById('details').innerHTML  = " ..... "
 

Так что, конечно, это только добавляет

Наивное решение состоит в том, чтобы добавить код ПЕРЕД циклами, который очищает innerHTML

 document.getElementById('details').innerHTML = ""
 

Гораздо лучшим решением было бы инициализировать строковую переменную перед циклами, добавить в строку внутри циклов, а затем обновить innerHTML один раз после циклов

 const api_url = "https://api.wazirx.com/api/v2/market-status";

async function get_data_from_api() {

    const response = await fetch(api_url);

    const data = await response.json();

    const len = Object.keys(data["markets"]).length;
    const len1 = Object.keys(data["assets"]).length;

    // this will hold the new HTML
    let html = "";
    
    for (let i = 0; i < len; i  ) {
        for (let j = 0; j < len1; j  ) {
            if (data['markets'][i]['baseMarket'] == data['assets'][j]['type'] amp;amp; data['markets'][i]['quoteMarket'] == "inr") {
                const name = data['assets'][j]['name'];
                const symbol = data['assets'][j]['type'];
                const currency = data['markets'][i]['quoteMarket'];
                const price = data['markets'][i]['buy'];
                html  = "<tr><td>"   name   "</td><td>"   symbol   "</td><td>"   currency   "</td><td>"   price   "</td></tr>";
            }
        }
    }
    // we have the new HTML - update the DOM only once per API call
    document.getElementById('details').innerHTML = html;
}
 

(Я взял на себя смелость объявить переменные там, где они необходимы, а не глобально)

Теперь: Вот альтернатива, которая очищает циклы for с помощью методов массива, таких как flatMap, фильтр, карта

 const api_url = "https://api.wazirx.com/api/v2/market-status";
async function get_data_from_api() {
    try {
        const response = await fetch(api_url);
        const data = await response.json();
        document.getElementById('details').innerHTML = Object.values(data.markets)
            .flatMap((market) =>
                Object.values(data.assets)
                                   // your if condition
                .filter((asset) => market.baseMarket == asset.type amp;amp; market.quoteMarket == 'inr')
                .map((asset) => {
                    const { name, type: symbol } = asset;
                    const { quoteMarket: currency, buy: price } = market;
                    return `<tr><td>${name}</td><td>${symbol}</td><td>${currency}</td><td>${price}</td></tr>`;
                })
            ).join('');
    } catch(error) {
        // handle error
    }
    setTimeout(get_data_from_api, 1000);
}

get_data_from_api();
 

Не уверен, но этот код может обновить только цену

 const api_url = "https://api.wazirx.com/api/v2/market-status";
async function get_data_from_api() {
    try {
        const target = document.getElementById('details');
        const response = await fetch(api_url);
        const data = await response.json();
        const addedHtml = Object.values(data.markets)
            .flatMap((market) =>
                Object.values(data.assets)
                                   // your if condition
                .filter((asset) => market.baseMarket == asset.type amp;amp; market.quoteMarket == 'inr')
                .map((asset) => {
                    const { name, type: symbol } = asset;
                    const { quoteMarket: currency, buy: price } = market;
                    return { id, name, symbol, currency, price };
                })
            )
            .map(({ name, symbol, currency, price }) => {
                const id = `${name}${symbol}${currency}`;
                let el = target.querySelector(`#${id}`);
                if (el) {
                    el.textContent = price;
                    return '';
                } else {
                    return `<tr><td>${name}</td><td>${symbol}</td><td>${currency}</td><td id="${id}">${price}</td></tr>`;
                }
            });
        if (addedHTML.length) {
            target.insertAdjacentHTML('beforeend', addedHtml.join(''));
        }
    } catch(error) {
        // handle error
    }
    setTimeout(get_data_from_api, 1000);
}

get_data_from_api();
 

Комментарии:

1. Ошибка произошла в моей консоли, которая «Не поймана (в обещании)». Ошибка типа: Объект.значения(…).flatmap не является функцией в get_data_from_api»

2. @harish — должен был быть flatMap … моя вина

3. Вопрос был «проблема с кодом», и одобренный ответ был «Как написать лучший код».

4. @harish, пожалуйста, взгляните на мой ответ. Это также помогло бы вам.

5. @Браво, Это было действительно забавно. Вопрос заключался в логической ошибке, которую он допустил в своем коде. Он спросил, почему его записи добавляются к существующим, а не удаляются из существующих и создаются новые. Но этот ответ был похож на то, как этот код можно улучшить до более эффективного уровня.