0

I am learing to use API an making a news website where you can search a term. I am using the code given below to do so.

var newsAccordion = document.getElementById("newsAccordion");

let news = {
  apiKey: "xxxxxxxxxx",
  fetchNews: function () {
    fetch(
      "https://gnews.io/api/v4/top-headlines?&country=in&lang=en&token=xxxxxxxxxxx"
    )
      .then((response) => response.json())
      .then((data) => {
        this.fetchCotent(data);
      });
  },
  fetchCotent: (data) => {
    console.log(data);
    size = data.articles.length;
    let newsHtml = "";
    for (var i = 0; i < size; i++) {
      const { title } = data.articles[i];
      const { publishedAt } = data.articles[i];
      const { url } = data.articles[i];
      const { image } = data.articles[i];
      const { description } = data.articles[i];
      console.log(title, publishedAt);

      var date = new Date(publishedAt).toLocaleString(undefined, {
        timeZone: "Asia/Kolkata",
      });
    }
    newsAccordion.innerHTML = newsHtml;
  },
  searchNews: (term) => {
    console.log(term);
    fetch(
      "https://gnews.io/api/v4/search?&lang=en&q=" +
        term +
        "&token=xxxxxxxxxx"
    )
      .then((response) => response.json())
      .then((data) => {
               this.serchNews();
            });
  },
  searchNews: (term) => {
      //code goes here
};

document
  .querySelector(".search button")
  .addEventListener("click", function (e) {
    e.preventDefault();
    news.searchNews(document.querySelector(".search-bar").value);
  });

window.onload = function () {
  news.fetchNews();
};

But the problem is its gaving an error sying

Uncaught (in promise) ReferenceError: showSearch is not defined at index.js:59

At index.js:59 it says:

Uncaught (in promise) TypeError: this.showSearch is not a function

My question is why is this happening and how can I solve it?

Thanks for any help in advance.

BIJAN ROY
  • 81
  • 10
  • Which lang is it, 2nd where is the rest of the code, the only code we see is the function you have written, where and which file are you calling it.. and many more question before we can suggest any solution – Nishant S Vispute May 17 '21 at 04:20
  • @NishantShamVispute The language is javascript. The rest of the code would be too long and it would not allow me to post such long code here, I have problem only in this specific part. Why is it saying that the function is not defined even if I have done so? – BIJAN ROY May 17 '21 at 04:25
  • `this` might not be what you think it is. Try `console.log(this)` before that line. – Barmar May 17 '21 at 04:26
  • `const showSearch = (data) => { }` just replace colon with equals – Vishwak May 17 '21 at 04:26
  • because this points to context of enclosing function where you defined the object containing your `searchNews` and `showSearch` properties. So if you define `showSearch` outside of the current object, the issue will be resolved. – Rahul Kumar May 17 '21 at 04:26
  • The problem as I see it is not within this part of the code.. because this part is only the definition of the actual function, the error you are getting is either in the ```index.js``` file or some other place which is called from inside of ```index.js``` – Nishant S Vispute May 17 '21 at 04:27
  • 1
    @Vishwak You can't put variable assignments inside object literals. – Barmar May 17 '21 at 04:27
  • What is the name of the object containing above piece of code? – Rahul Kumar May 17 '21 at 04:29
  • How do you call `searchNews`? – VLAZ May 17 '21 at 04:34
  • @VLAZ With this function document .querySelector(".search button") .addEventListener("click", function (e) { e.preventDefault(); news.searchNews(document.querySelector(".search-bar").value); }); – BIJAN ROY May 17 '21 at 04:35
  • @NishantShamVispute This is excrept from index.js only – BIJAN ROY May 17 '21 at 04:42
  • Can you post the Complete Error log to your question.. this much code is not providing any insight – Nishant S Vispute May 17 '21 at 04:46
  • @NishantShamVispute I have done already... thats all the error I am getting – BIJAN ROY May 17 '21 at 04:48

2 Answers2

1

Replace arrow function to regular function for searchNews and showSearch. So that it gets the current scope using this, because arrow function doesn't have it's own context; it takes the context of enclosing function.

searchNews: function(term) {
    console.log(term);
    fetch(
      "https://gnews.io/api/v4/search?&lang=en&q=" +
        term +
        "&token=368ddd2e4d1c1c559f1fb904cb1e09fa"
    )
      .then((response) => response.json())
      .then((data) => {
        this.showSearch(data);
      });
  },
  showSearch: function(data) {
    size = data.articles.length;
    // your code...
  },

Working code example:

const news = {
    searchNews: function (term) {
        console.log("search news: ", term);
        fetchApi("https://gnews.io/api/v4/search")
            .then((response) => response.json())
            .then((data) => {
              console.log("received data:");
              this.showSearch(data);
            });
    },
    showSearch: function (data) {
        console.log("showSearch: ", data);
        // your code...
    }
}

function fetchApi(url) { // fetch api stub
    return new Promise((resolve, reject) => {
        const response = {
            data: { id: 123, title: "test-title" },
            statusCode: 200
        }
        let responseObj = new Response(JSON.stringify(response))
        setTimeout(resolve(responseObj), 500);
    })
}

document.querySelector("#search-button").addEventListener("click", function (e) { 
  e.preventDefault(); 
  news.searchNews(document.querySelector("#search-bar").value); 
});
<html>
<head></head>
<body>

<div>Enter search title: 
<input type="text" id="search-bar">
</div>
<div style="margin-top: 20px">
<button id="search-button">Search News</button>
</div>

</body>
</html>
Rahul Kumar
  • 3,009
  • 2
  • 16
  • 22
0

This is because of the misunderstanding of this in Javascript. Please read the this in Javascript.

Anyway you can modify the code as follows.

const obj = {

  searchNews: (term) => {
    console.log(term);
    function cbFunc(data) {
      this.showSearch(data);
    }
    fetch(
      "https://gnews.io/api/v4/search?&lang=en&q=" +
        term +
        "&token=368ddd2e4d1c1c559f1fb904cb1e09fa"
    )
      .then((response) => response.json())
      .then(cbFunc.bind(obj));
  },
  showSearch: (data) => {
    size = data.articles.length;
    let newsHtml = "";
    for (var i = 0; i < size; i++) {
      const { title } = data.articles[i];
      const { publishedAt } = data.articles[i];
      const { url } = data.articles[i];
      const { image } = data.articles[i];
      const { description } = data.articles[i];

      var date = new Date(publishedAt).toLocaleString(undefined, {
        timeZone: "Asia/Kolkata",
      });

      console.log(title, date, url, image, description);
    }
  }
}

Please place emphasis on bind call, where obj should be your wrapper object(at the top line of the code).

TopW3
  • 1,477
  • 1
  • 8
  • 14