我用不同的参数进行了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
我如何使其工作?
奖励:我如何将这些键值对分配给每个对象?
解决方法:
有关具体错误消息的原因,请参见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没有做任何事情将它们传播给调用者.
但是,似乎很奇怪,不要将返回值用于任何事情.也许map和Promise.all:
const results = await Promise.all([
['followers_url', 'contributorFollowers'],
['gists_url', 'contributorGists'],
['repos_url', 'contributorRepositories'],
].map(pair => this.getContributorProperties(pair[0], pair[1])));
…如果来电者不这样做,一定要处理错误.
请注意,getContributorProperties函数中有两个错误:
>它不会等待axios.get在返回之前完成(异步函数不会自动等待promise,你必须是显式的)
>它不处理axios.get返回的promise的拒绝
我很好奇,如果重复调用this.addLinkToContributor三次是正确的,以及它是否可能在第二次浪费.
在评论中你问过:
Results
are 3 arrays of the same objects (contributors) with just one property changed each. So one array has contributors with gists, another with followers, etc. Do I now somehow concatenate them or is it better to do that ingetContributorProperties
function?
那是我的直觉.就像是:
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,以便上述内容不会混淆其隐喻…)