0

Oh once again I have those Promise.all blues:( I have a function that makes an array of fetch call's from provided urls and then we want to retrieve data via a Promise.all and return array of reponses or better yet just return the promise to calling function. . The problem is this results in error w/console showing:

There was problem retrieving data. TypeError: r.json is not a function

The code for the function is :

 const getLeagueLeaders = (url, params) => {
  // First let's create the array of url's
  let queryURLs = [];

  params.forEach((param) => {
    queryURLs.push(
      fetch(`${url}${new URLSearchParams(param)}`, {
        method: "get",
        headers: {
          Authorization:
            "Basic ==",
        },
      }).then((res) => res.json())
    );
  });

  return (
    Promise.all(queryURLs)
      // map array of responses into an array of response.json() to read their content
      .then((responses) => responses.map((r) => r.json()))
      .catch((err) => {
        console.error("There was problem retrieving data.", err);
      })
  );
};
    
    module.exports = getLeagueLeaders;

And in Vue component

 mounted: async function () {
        const leagueLeadersResponseArray = await getLeagueLeaders(
          this.fetchBaseUrl,
          this.params
        );
this.qbLeaders =
      leagueLeadersResponseArray[0].cumulativeplayerstats.playerstatsentry;

Obviously leagueLeadersResponseArray is undefined. I researched .json() and dont see how I am using it incorrectly. At first i thought I needed a Promise.all wrapper for the responses.map((r) => r.json()) but that did no good either. I looked at this link but I am not using fetch as he is. Any guidance much appreciated....

Updated working code for anybody else:

// ---------- src/js/modules/ ------------------ //

/* jshint ignore:start */
// Make function to retrieve League Leaders in a Category

const getLeagueLeaders = (url, params) => {
  // First let's create the array of url's
  let queryURLs = [];

  params.forEach((param) => {
    queryURLs.push(
      fetch(`${url}${new URLSearchParams(param)}`, {
        method: "get",
        headers: {
          Authorization:
            "Basic ==",
        },
      }).then((res) => res.json())
    );
  });

  return Promise.all(queryURLs).catch((err) => {
    console.error("There was problem retrieving data.", err);
  });
};

module.exports = getLeagueLeaders;
Alan
  • 1,067
  • 1
  • 23
  • 37
  • 2
    `fetch()` is being treated as part of a string template, not a JavaScript function like you intend. Strings don't have a function `.json()`. Call the actual `fetch` function without surrounding it in backticks like ```fetch(`your string literal URL`, {/* your request config object */})```. Also, `then(data => { return data })` does nothing. You need to `return Promise.all` instead, which returns an array of promises that will resolve to JSON after another `Promise.all`. – ggorlen Nov 27 '20 at 23:43
  • a string does not have a `.json` method - check the content of `queryURLs` array – Bravo Nov 27 '20 at 23:51

1 Answers1

1

Your template string is around the entire fetch when it should only be in the argument to fetch:

  params.forEach((param) => {
    queryURLs.push(fetch(`${url}${new URLSearchParams(param)}`, {
      method: "get",
      headers: {
        Authorization:
          "Basic *****==",
      }
    }));
  });

Then, you have a .then(data => {return data}), which doesn't do anything since the return returns from the then callback, not the function. You should instead return the promise that Promise.all gives you:

  return Promise.all(queryURLs)
    // map array of responses into an array of response.json() to read their content
    .then((responses) => responses.map((r) => r.json())) // Get error There was problem retrieving data. TypeError: r.json is not a function
    .catch((err) => {
      console.error("There was problem retrieving data.", err);
    });
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • Thanks! How do I consume the returned data. I thought this.qbLeaders = leagueLeadersResponseArray[0].cumulativeplayerstats.playerstatsentry; would give me access to first response from API. But I'm getting it is undefined. – Alan Nov 28 '20 at 01:11
  • You should `console.log(leagueLeadersResponseArray)` to make sure the data is how you expected. – Aplet123 Nov 28 '20 at 01:15
  • Now I'm confused. I thought once Promise.all settles then leagueLeadersResponseArray would have my three reposnses in it as an array per docs. Instead I have this:This is return leagueLeaders array [object Promise],[object Promise],[object Promise]. Any suggestions. – Alan Nov 28 '20 at 01:20
  • Oh, you'll probably want to change `queryURLs.push(fetch(...))` to `queryURLs.push(fetch(...).then((res) => res.json())` and it'll work. – Aplet123 Nov 28 '20 at 01:22
  • See updated code. Now we're back to There was problem retrieving data. TypeError: r.json is not a function error. ??? – Alan Nov 28 '20 at 01:40
  • Truly is simple and elegant solution once you get the damn thing working! Using Promises that is.. – Alan Nov 28 '20 at 02:02