将async / await与for循环一起用于嵌套Axios调用

时间:2018-10-07 22:48:55

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

我正在使用Axios对Facebook Graph执行GET请求,以获取用户管理的Facebook页面列表。一旦有了这些,就可以使用for loop对Facebook Graph执行另一个GET请求,以在用户管理的每个Facebook Page上提取数据。我在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使其看起来像下面的样子,并看到两个调用都成功转到Facebook Graph,从而验证了const pages循环是否有效。

  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个人资料,因此我不得不在下面修改他的示例以通过棉绒。再次感谢!

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

1 个答案:

答案 0 :(得分:0)

Promise.all()对于user来说不是必需的,因为它不是一个承诺,因为您已经使用axios.get()解开了await的包装。 user.data.accounts.data.map(...)是承诺的数组(在您做出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会暂停控制流,直到诺言得以解决为止,因此,如果您有不需要顺序执行的请求,最好在axios.get()处理所有await之前使用SELECT * INTO TempFile FROM OPENROWSET( BULK 'input/File.csv', DATA_SOURCE = 'AzureBlob', SINGLE_CLOB) 创建所有请求如果可以的话,立即将它们保存。