forEach循环与异步代码?

时间:2017-09-25 10:12:00

标签: javascript reactjs foreach async-await frontend

我使用不同的参数进行3次函数调用:

this.getContributorProperties('followers_url', 'contributorFollowers');
this.getContributorProperties('gists_url', 'contributorGists');
this.getContributorProperties('repos_url', 'contributorRepositories');

此功能如下所示:

async getContributorProperties(propertyUrl, propertyName) {
    const contributors = await this.addLinkToContributor();
    for (let i = 0; i < 10; i += 1) {
      axios.get(`${contributors[i][propertyUrl]}?per_page=100&${API_KEY}`).then((res) => {
        contributors[i][propertyName] = res.data.length;
      });
    }
    return contributors;
}

它遍历一个贡献者数组(对象类型),并为每个贡献者进行API调用。我需要为它们中的每一个进行3次API调用,因此在开始时进行三次调用。 为了干掉我的代码,我想像这样制作一个forEach循环:

[
      ['followers_url', 'contributorFollowers'],
      ['gists_url', 'contributorGists'],
      ['repos_url', 'contributorRepositories'],
    ].forEach(this.getContributorProperties);

forEach循环位于componentDidMount() 当我拨打3个电话时,它可以正常工作。但是,当我为每个人做的时候,我得到一个错误:

Uncaught (in promise) TypeError: Cannot read property 'addLinkToContributor' of undefined

如何让它发挥作用?

BONUS:我如何将这些键值对分配给每个对象?

1 个答案:

答案 0 :(得分:6)

请参阅How to access the correct this inside a callback?和/或How does the "this" keyword work?了解您收到该特定错误消息的原因。

但从根本上说,你无论如何都不想将这个功能传递到forEach,因为forEach并没有通过该功能。

相反,只需使用箭头功能:

[
  ['followers_url', 'contributorFollowers'],
  ['gists_url', 'contributorGists'],
  ['repos_url', 'contributorRepositories'],
].forEach(pair => this.getContributorProperties(pair[0], pair[1]).catch(err => {/*...handle error...*/});

注意错误处理;我们不希望遭到未经处理的拒绝,forEach没有做任何事情将其传播给来电者。

但是,似乎很奇怪,不要将返回值用于任何事情。可能是mapPromise.all

const results = await Promise.all([
  ['followers_url', 'contributorFollowers'],
  ['gists_url', 'contributorGists'],
  ['repos_url', 'contributorRepositories'],
].map(pair => this.getContributorProperties(pair[0], pair[1])));

...如果来电者赢了,肯定会处理错误。

请注意getContributorProperties功能中存在两个错误:

  1. 它不会等到axios.get完成才能返回(async函数不自动 - await承诺,你必须明确)

  2. 它没有处理axios.get

  3. 返回的承诺的拒绝

    我很好奇,如果重复拨打this.addLinkToContributor三次是正确的,以及这两次是否可能是浪费。

    在评论中你曾问过:

      

    Results是3个相同对象(贡献者)的数组,每个只更改一个属性。所以一个数组有贡献者有gists,另一个有关注者等等。我现在以某种方式连接它们,还是在getContributorProperties函数中做得更好?

    这将是我的直觉。类似的东西:

    async getContributorProperties(properties) {
        const contributors = await this.addLinkToContributor();
        return Promise.all(contributors.map(contributor =>
          Promise.all(properties.map(property =>
            axios.get(`${contributor[property.url]}?per_page=100&${API_KEY}`).then(res => {
              contributor[property.name] = res.data.length;
            })
          ));
        ));
    }
    

    这样叫:

    const results = await this.getContributorProperties([
      {url: 'followers_url', name: 'contributorFollowers'},
      {url: 'gists_url',     name: 'contributorGists'},
      {url: 'repos_url',     name: 'contributorRepositories'}
    ]);
    

    (我们确实需要await.all concept,以便上述内容不会混淆其隐喻......)