簡體   English   中英

變量可能超出范圍

[英]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 ...

您的推送和寫入操作將以無保證的順序進行,不一定是順序的。

其中Lreseponse.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM