0

I want to push data from promise to array (coursesArray) and then use the array values else where. I am using node-fetch library to query the API. Currently when i log array inside the promise, it has values(coursesOne) however when i log the array outside the promise, it is empty(coursesTwo). How do i go about implementing the ideal solution so that coursesArray is filled with data when getCoursesForSitemap() executes

Here is what i have implemented so far

const coursesArray = [];

const getCoursesForSitemap = () => {
  fetch(coursesUrl)
    .then(res => res.json())
    .then(json => {
      json.courses.results.map(course => {
        return coursesArray.push(course.slug);
      });
      console.log('coursesOne', coursesArray);
    })

    .catch(error => {
      console.log(error);
    });
};
getCoursesForSitemap();
console.log('coursesTwo', coursesArray);
freetyy
  • 109
  • 10

2 Answers2

1

Refactoring your code to use async/await, and not making it mutate the out-of-closure/global variable, this should work for you.

const getCoursesForSitemap = async () => {
  const result = await fetch(coursesUrl);
  const json = await result.json();
  return json.courses.results.map(course => course.slug);
};
const coursesArray = await getCoursesForSitemap();
console.log('coursesTwo', coursesArray);

In case your environment doesn't support top-level async/await, you'll need to execute the async code in e.g. an IIFE:

(async function() {
  const coursesArray = await getCoursesForSitemap();
  console.log('coursesTwo', coursesArray);
}());

(That function will also return a promise you can .then() or await on...)

AKX
  • 152,115
  • 15
  • 115
  • 172
  • I would like to know what's the benefit of using `async` / `await` over `then` and promise ? – Nicolas Nov 04 '19 at 16:29
  • Am getting this error `Can not use keyword'await' outside an async function` – freetyy Nov 04 '19 at 16:31
  • 1
    @Nicolas Clearer, flatter code with less indentation. Async/await is (mostly) just syntax sugar for promise management anyway. – AKX Nov 04 '19 at 16:38
  • @freetyy Ah, yeah, you are running in an environment that doesn't support top-level async/await. I'll augment the answer. – AKX Nov 04 '19 at 16:39
  • How do i access the values that the async code returns for example if i want to assign the values you are logging(coursesTwo) to some other array. Currently when i assign a variable to the IIFE above and i try to log the variable it shows `Promise { }` – freetyy Nov 04 '19 at 16:57
  • It's a promise – You will have to `await` for the result, or apply `.then()` on it. – AKX Nov 04 '19 at 16:59
  • Can you demonstrate how I can achieve that? I am interested in what the promise returns. – freetyy Nov 04 '19 at 17:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/201850/discussion-between-freetyy-and-akx). – freetyy Nov 04 '19 at 17:08
  • 1
    I can link you the MDN tutorial on async/await – you'll find it uses `fetch()`, like you do. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await – AKX Nov 04 '19 at 17:09
0

You are trying to log the values before they are resolved from your promise. That's why it's not working. You need to wait for the Promise to be resolve before trying to show them.

You also need to return the promise .

const coursesArray = [];

const getCoursesForSitemap = () => {
  return fetch(coursesUrl)
    .then(res => res.json())
    .then(json => {
      json.courses.results.forEach(course => {
        return coursesArray.push(course.slug);
      });
      console.log('coursesOne', coursesArray);
    })

    .catch(error => {
      console.log(error);
    });
};
getCoursesForSitemap().then(() => {
    console.log('coursesTwo', coursesArray);
});

I've also changed the map function you use for a forEach since you don't need to change the value of the json.courses.results array.

Nicolas
  • 8,077
  • 4
  • 21
  • 51