Setinterval 函数重复 HTML 内容

Setinterval Function Repeating the HTML contents

我有一个 table 行内容是从 API 中获取的,而我使用 setinterval 函数只是重复更新的 table 行内容。

例如:(这是一个示例输出,不是实际的)

假设我有内容

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'] && 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);

您只是将内容附加到节点

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'] && 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);

您的代码不断添加到 table 的原因是因为您只添加了

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'] && 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;
}

(I took the liberty of declaring the variables where they are needed rather than globally)

现在:这是一个使用 flatMap、filter、map 等数组方法清理 for 循环的替代方法

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 && 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 && 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();

除了已接受的答案。我还建议您在下面使用带有 wait 函数的 while 循环,而不是 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;
    }
  }
})();