【问题标题】:Using async/await with a for loop for nested Axios calls将 async/await 与 for 循环一起用于嵌套的 Axios 调用
【发布时间】:2019-03-12 14:42:12
【问题描述】:

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

我的问题是:我无法从 const pages 中的 Axios 调用中获取结果以填充 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);
      });
  });

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

回答

感谢Patrick Roberts 的帮助。由于我使用的是 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);
    }
  }

【问题讨论】:

  • Array.forEach() 返回undefined;你会想改用Array.map()
  • 不是很相关,但是你为什么要做 access_token: ${token} 而不仅仅是 access_token: token
  • 你传递给map的函数需要returnaxios.get(...)
  • @ItayMoav-Malimovka 我真的不记得了,感谢您帮助我通过没有不必要的代码来改进它。

标签: javascript node.js async-await axios es6-promise


【解决方案1】:

Promise.all() 对于user 来说不是必需的,因为它不是一个承诺,因为您已经使用await 解开axios.get()user.data.accounts.data.map(...) 是一个 array 承诺(在你做出 the fix I suggested 之后),所以你也不应该直接 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);
  }
}

这样,userpages 请求可以同时发生而不是顺序发生。 await 暂停控制流直到 promise 被解决,所以如果你有不需要顺序的请求,最好在 awaiting 之前用 axios.get() 创建所有它们,如果你可以。

【讨论】:

  • 感谢帕特里克的例子。因为我使用的是 Airbnb ESLint 规则,所以我只需要稍微修改一下,它就可以工作了。非常感谢!
猜你喜欢
  • 2020-09-24
  • 2021-02-27
  • 2022-06-23
  • 2018-09-03
  • 2018-03-25
  • 2021-08-15
  • 1970-01-01
  • 2020-03-07
相关资源
最近更新 更多