// 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]中的内容在第一次调用时呈现未定义的状态,然后在下一次调用时呈现正确的状态,然后呈现未定义的状态,依此类推,在未定义和数据之间采用这种交替模式。这是怎么回事?
答案 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。
此外,由于这都是异步操作,因此顺序可能会根据获取的完成情况而改变,这可能导致无法预测的行为。