[英]variable probably outside of scope
盡管代碼乍一看似乎有點沉重(可能仍然如此),但它很簡單。 我要做的就是從JSON文件中讀取一些數據(格式如下:
{"news":[{}]}
)
,然后將一些信息推送到一個數組中,該數組是從來自newsapi.org服務器之一的另一個JSON文件獲得的。 我的問題可能是由於吊裝引起的,但我不知道如何解決。 在控制台中,它吐出Uncaught TypeError: Cannot read property 'title' of undefined
。
以下是我已停用代碼的摘錄。
(我知道我的代碼看起來很亂:P)
function appendNews(id) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://newsapi.org/v2/top-headlines?sources=" + id +
"&apiKey=8fdd732e76664e06b177a20fb295129c", true);
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);
xhr.onreadystatechange = processRequest();
function processRequest() {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
var container = document.getElementById("newsContainer");
for (var i = 0; i < response.articles.length; i++) {
fs.readFile('./data/events/news.json', 'utf8', function(err, data) {
if (err) {
console.log(err)
} else {
var file = JSON.parse(data)
file.news.push({
"title": response.articles[i].title,
"description": response.articles[i].description,
"url": response.articles[i].url,
"urlImg": response.articles[i].urlToImage,
"time": response.articles[i].publishedAt,
"sourceAndAuthor": response.articles[i].author + " (" +
response.articles[i].source.name + ")"
})
var toStringify = JSON.stringify(file);
fs.writeFile('./data/events/news.json', toStringify, 'utf8', function(err) {
if (err) {
console.log(err);
} else {
}
});
}
});
}
}
編輯:在我的代碼的更下方,我使用相同的變量,然后它起作用:
var holder = document.createElement("button");
holder.setAttribute("id", "newsHolder");
holder.setAttribute("onclick", "openArticle(" + "'" +
response.articles[i].title + "'" + ")")
var title = document.createElement("div");
title.setAttribute("id", "newsTitle");
title.innerHTML = response.articles[i].title;
var image = document.createElement("img");
image.setAttribute("src",response.articles[i].urlToImage)
image.setAttribute("id", "articleImage");
holder.appendChild(title);
holder.appendChild(image);
container.appendChild(holder);
fadeIn("newsContainer",1,0.01,1);
這是控制流程中的一個主要問題:
for (var i = 0; i < response.articles.length; i++) {
fs.readFile('./data/events/news.json', 'utf8', function(err, data) {
...
var file = JSON.parse(data)
...
var toStringify = JSON.stringify(file);
fs.writeFile('./data/events/news.json', toStringify, 'utf8', function(err) {
});
});
}
這樣的寫法表明對異步編程完全缺乏了解,因為真正發生的是一種競爭情況,在這種情況下,最后一個成功的fs.writeFile()
只會將response.articles
一個條目追加到JSON,即使您要修復TypeError
。
您期望代碼像這樣運行:
i=1 2 3 4 5 ... L
r r r r r
p p p p p
w w w w w
其中r, p, w
代表fs.readFile()
, file.news.push()
和fs.writeFile()
,但實際上是這樣的:
i=1 2 3 4 5 ... L
r r r r r ...
p p p p p ...
w w w w w ...
您的推送和寫入操作將以無保證的順序進行,不一定是順序的。
其中L
是reseponse.articles.length
,而您嘗試在i === response.articles.length
時訪問response.articles[i]
,因此當然那里沒有article
。
第一個變化是使用
for (let i = 0; i < response.articles.length; i++) {
但這不能解決上面解釋的競爭條件,只會導致i
具有詞法作用域,因此至少您不會超出范圍。
為了避免不必要的讀寫,您只需將fs.readFile()
循環一次,遍歷您的articles
並將其推送到回調中的file.news
中,然后在for
循環結束后再將其fs.writeFile()
。 看起來像這樣:
// add your event listener BEFORE sending
xhr.addEventListener('load', processRequest, false);
xhr.send();
function processRequest() {
// no need to check readyState and status if you use the `load` event
fs.readFile(..., (err, data) => {
// handle error
if (err) {
console.log(err);
return;
}
const { articles = [] } = JSON.parse(xhr.responseText);
const file = JSON.parse(data);
for (const article of articles) {
const {
title,
description,
url,
urlToImage: urlImg,
publishedAt: time,
author,
source: { name }
} = article;
file.news.push({
title,
description,
url,
urlImg,
time,
sourceAndAuthor: `${author} (${name})`
});
}
const json = JSON.stringify(file);
fs.writeFile(..., (err) => {
if (err) {
console.log(err);
return;
}
});
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.