5

I am using Axios to perform a GET request against Facebook Graph to get the list of Facebook Pages the user manages. Once I have that, then I am using a for loop to perform another GET request against Facebook Graph to pull data on each Facebook Page that the user manages. I am doing this inside of an async function with a Promise at the end to join all the data together into a single const fbProfile.

My issue is: I cannot get the results from the Axios call in const pages to populate pages array.

My code is below:

  async function getfbProfile(token) {
    try {
      const user = await axios.get('https://graph.facebook.com/me', {
        params: {
          access_token: `${token}`,
          fields: 'picture,accounts',
        },
      });
      const pages = await user.data.accounts.data.forEach((err, pageInfo) => {
        axios.get(`https://graph.facebook.com/${user.data.accounts.data[pageInfo].id}`, {
          params: {
            access_token: `${token}`,
            fields: 'picture,name',
          },
        });
      });
      const fbProfile = await Promise.all([user, pages]);
      debug(fbProfile);
    } catch (err) {
      debug(err.stack);
    }
  }

I know that the first call goes through and the for loop calls go through. I verified the for call loop works by modifying const pages to look like below and seeing both calls successfully go to Facebook Graph.

  const pages = await user.data.accounts.data.forEach((err, pageInfo) => {
    axios.get(`https://graph.facebook.com/${user.data.accounts.data[pageInfo].id}`, {
      params: {
        access_token: `${token}`,
        fields: 'picture,name',
      },
    })
      .then((result) => {
        debug(result);
      });
  });

I would greatly appreciate any help. I've been wracking my brains on this for the last two days. Thank you for any help you can give.

ANSWER

Thanks to Patrick Roberts for his help. Since I am using Airbnb's ESLint profile, I had to modify his example below to pass linting. Thanks again!

  async function getfbProfile(token) {
    try {
      const user = await axios.get('https://graph.facebook.com/me', {
        params: {
          access_token: token,
          fields: 'picture,accounts',
        },
      });
      const pages = Promise.all(user.data.accounts.data.map(({ id }) => axios.get(`https://graph.facebook.com/${id}`, {
        params: {
          access_token: token,
          fields: 'picture,name',
        },
      })));
      const fbProfile = await Promise.all([user, pages]);
      debug(fbProfile);
    } catch (err) {
      debug(err.stack);
    }
  }
4
  • Array.forEach() returns undefined; you'll want to use Array.map() instead. Commented Oct 7, 2018 at 22:51
  • 1
    not really related, but why do you do access_token: ${token} instead of just access_token: token Commented Oct 7, 2018 at 22:51
  • 1
    The function you're passing to map needs to return the axios.get(...) Commented Oct 7, 2018 at 23:04
  • @ItayMoav-Malimovka I honestly can't remember, thanks for helping me make that better by not having unnecessary code in there. Commented Oct 7, 2018 at 23:45

1 Answer 1

2

The Promise.all() isn't necessary for user because it isn't a promise, since you've unwrapped axios.get() using await already. user.data.accounts.data.map(...) is an array of promises (after you make the fix I suggested), so you shouldn't await it directly either.

Here's a simplified approach:

async function getfbProfile(token) {
  try {
    const user = axios.get('https://graph.facebook.com/me', {
      params: {
        access_token: token,
        fields: 'picture,accounts',
      },
    });
    const pages = Promise.all(user.data.accounts.data.map(({ id }) => {
      return axios.get(`https://graph.facebook.com/${id}`, {
        params: {
          access_token: token,
          fields: 'picture,name',
        },
      });
    }));
    const fbProfile = await Promise.all([user, pages]);
    debug(fbProfile);
  } catch (err) {
    debug(err.stack);
  }
}

This way, user and pages requests can occur concurrently rather than sequentially. await halts control flow until the promise is resolved, so if you have requests that don't need to be sequential, it's better to create all of them with axios.get() before awaiting all of them at once, if you can.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the example Patrick. Since I am using Airbnb ESLint rules I had to modify it just a little, however, it works. Thank you VERY much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.