数组数据每隔第二个事件仅呈现到HTML表一次,否则未定义

时间:2018-09-16 23:02:34

标签: javascript html arrays json dom

// 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]中的内容在第一次调用时呈现未定义的状态,然后在下一次调用时呈现正确的状态,然后呈现未定义的状态,依此类推,在未定义和数据之间采用这种交替模式。这是怎么回事?

2 个答案:

答案 0 :(得分:1)

您正在renderData完成之前调用fetch,因此尚未完成提取。尝试将其移至then内部以了解我的意思。

fetch是异步的-它必须等待网络响应-并且您在then中编写的代码等待其完成,但是renderData被正确调用在该项目被推到阵列上之前。

即使您进行了多次提取并以此方式推入数组,即使进行了此更改,您的代码也似乎容易出错-tags可能会被推出顺序而与{{ 1}},如您所愿。

答案 1 :(得分:0)

Fetch和链接的thens将返回Promise对象。您可以将所有这些内容推送到一个数组中,并使用Promise.all()在调用renderData()之前检查所有获取是否完整,然后

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

// 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();
    });
}

重要的是要注意,当将then链接到一个promise时,分配给变量的promise是最后链接的then的promise。

此外,由于这都是异步操作,因此顺序可能会根据获取的完成情况而改变,这可能导致无法预测的行为。