数组数据每秒仅向HTML表呈现一次,否则为undefined

问题描述 投票:0回答:2
// Relevant code: 

const searchBtn = document.getElementById("search-btn");
const input = document.getElementById("input");
const leftTable = document.querySelector("#left-table");
let url = "https://api.github.com/search/repositories?q=?";
let tagsUrl;
let dataArr;
let names = [];
let language = [];
let latestTag = [];
let tableDataArr = [names, language, latestTag];

// Fetch first 2 items for repos containing user query
function search(newURL) {
  fetch(newURL, {
    headers: {
      "Authorization": "xxxx" 
    }
  })
    .then(resp => {
      return resp.json();
    })
    .then(data => {
      dataArr = data.items.slice(0, 2);
      return extractData();
    });
  input.value = ""; 
}

// Extract necessary values from returned object (language, name, latest tag) and push to corresponding arrays
function extractData() {
  dataArr.forEach(i => {
    names.push(i.full_name);
    language.push(i.language);
    fetch(i.tags_url)
      .then(resp => {
        return resp.json();
      })
      .then(resp => {
        if (resp[0]) {
         latestTag.push(resp[0].name);
        } else {
         latestTag.push(" ");
        }
        return console.log(tableDataArr);
      });
    //  getLatestTag(i.tags_url);
  });
  renderData();
}

// Render array data to HTML table
function renderData() {
  tableDataArr[0].forEach((i, j) => {
    let newRow = document.createElement("tr");
    newRow.className = "row";
    newRow.innerHTML = `<td class='cell'>${i}</td>
    <td class='cell'>${tableDataArr[1][j]}</td>
    <td class='cell'>${tableDataArr[2][j]}</td>
    <td class='cell'><button class='add-btn'>Add</button></td>`;
    leftTable.appendChild(newRow);
  });
}

// User input event listeners
searchBtn.addEventListener("click", () => {
  search(url + input.value);
});

input.addEventListener("keyup", e => {
  if (e.keyCode === 13) {
    search(url + input.value);
  }
});

我需要tableDataArr中每个数组的内容在事件监听器触发后呈现给HTML表。 tableDataArr [0]和tableDataArr [1]中的内容每次都会呈现,没有任何问题。

但是,tableDataArr [2]中的内容在第一次调用时呈现未定义,然后在下一次调用时正确呈现,然后是未定义的,依此类推,在undefined和数据之间使用这种交替模式。这里发生了什么?

javascript html arrays json dom
2个回答
0
投票

Fetch和链接的thens将返回一个Promise对象。你可以把所有这些都推到一个数组中,并在调用renderData()之前使用Promise.all()检查你的所有提取和文件是否完整

此示例代码将指导您...

// Extract necessary values from returned object (language, name, latest tag) and push to corresponding arrays
function extractData() {
  let psArr = [];
  dataArr.forEach(i => {
    names.push(i.full_name);
    language.push(i.language);
    let ps = fetch(i.tags_url)
      .then(resp => {
        return resp.json();
      })
      .then(resp => {
        if (resp[0]) {
         latestTag.push(resp[0].name);
        } else {
         latestTag.push(" ");
        }
        return resp;
      });
    psArr.push(ps);
    //  getLatestTag(i.tags_url);
  });
  Promise.all(psArr).then(()=>{
    renderData();
    });
}

重要的是要注意当thens链接到一个承诺时,分配给变量的承诺是最后一个链式then的承诺。

此外,由于这是异步的,因此顺序可以根据提取的完成而改变,这可能导致不可预测的行为。


1
投票

你在renderData完成之前调用fetch所以它还没有完成提取。尝试将它移动到then内部,看看我的意思。

fetch是异步的 - 它必须等待网络响应 - 你在then中编写的代码等待它完成,但是在将该项目推入阵列之前,renderData正在被立即调用。

看起来即使使用此更改,如果您正在进行多次提取并以这种方式推送到阵列,您的代码也可能容易出错 - 可能会导致tags无法正常运行,并且无法与您预期的names匹配。

© www.soinside.com 2019 - 2024. All rights reserved.