forEach循环与异步代码?

n3s*_*tle 3 javascript foreach frontend async-await reactjs

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

this.getContributorProperties('followers_url', 'contributorFollowers');
this.getContributorProperties('gists_url', 'contributorGists');
this.getContributorProperties('repos_url', 'contributorRepositories');
Run Code Online (Sandbox Code Playgroud)

这个函数看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

[
      ['followers_url', 'contributorFollowers'],
      ['gists_url', 'contributorGists'],
      ['repos_url', 'contributorRepositories'],
    ].forEach(this.getContributorProperties);
Run Code Online (Sandbox Code Playgroud)

forEach循环在进行componentDidMount() 当我进行3次调用时,它可以正常工作.但是当我为每个人做的时候我得到一个错误:

Uncaught (in promise) TypeError: Cannot read property 'addLinkToContributor' of undefined
Run Code Online (Sandbox Code Playgroud)

我如何使其工作?

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

T.J*_*der 6

请参阅如何this在回调中访问正确的内容?和/或"this"关键字如何工作?为什么你有这个特定的错误信息.

但从根本上说,你不会只想传递那个函数forEach,因为forEach它没有传递它想要的功能.

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

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

注意错误处理; 我们不希望未处理的拒绝,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])));
Run Code Online (Sandbox Code Playgroud)

...如果来电者不这样做,一定要处理错误.


请注意,您的getContributorProperties功能有两个错误:

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

  2. 它不会处理对所返回的承诺的拒绝 axios.get

如果重复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;
        })
      ));
    ));
}
Run Code Online (Sandbox Code Playgroud)

像这样叫:

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

(我们真的需要这个await.all概念,以便上述内容不会混淆其隐喻...)