首页 > 解决方案 > 将 async/await 与 for 循环一起用于嵌套的 Axios 调用

问题描述

我正在使用 Axios 对 Facebook Graph 执行 GET 请求,以获取用户管理的 Facebook 页面列表。一旦我有了它,我就会使用 afor loop对 Facebook Graph 执行另一个 GET 请求,以在用户管理的每个 Facebook 页面上提取数据。我在async functionaPromise中执行此操作,最后将所有数据连接到一个const fbProfile.

我的问题是:我无法从 Axios 调用中获取结果const pages以填充pages数组。

我的代码如下:

  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);
    }
  }

我知道第一个调用通过并且 for 循环调用通过。我for call通过修改const pages如下所示并看到两个调用都成功转到 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);
      });
  });

我将不胜感激任何帮助。这两天我一直在为此绞尽脑汁。感谢您提供的任何帮助。

回答

感谢帕特里克·罗伯茨的帮助。由于我使用的是 Airbnb 的 ESLint 配置文件,因此我必须修改下面的示例以通过 linting。再次感谢!

  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);
    }
  }

标签: javascriptnode.jsasync-awaitaxioses6-promise

解决方案


ThePromise.all()不是必需的,user因为它不是一个承诺,因为你已经axios.get()使用await了。user.data.accounts.data.map(...)一系列承诺(在你做出我建议的修复之后),所以你也不await应该直接这样做。

这是一个简化的方法:

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);
  }
}

这样,user请求pages可以同时发生而不是顺序发生。await暂停控制流直到promise被解决,所以如果你有不需要顺序的请求,如果可以的话,最好用axios.get()beforeawait一次创建所有请求。


推荐阅读