需求:利用Github V3版本的API,获取某个用户star的项目个数。
而用户的api并没有单独提供star个数,而是提供了这样的接口
"starred_url": "https://api.github.com/users/tj/starred{/owner}{/repo}"
查了一下,,github api采用分页技术,如果用上述默认接口,最多只能返回30条内容。因而需要利用参数获取:https://api.github.com/users/tj/starred?page=1&per_page=100,per_page最大可为100.
也就是说我需要这样GET多个接口,直到获取的接口返回[ ]:
axios.get(`/users/${app.userName}/starred?page=${i++}&per_page=100`)
循环程序是同步执行的,GET请求是异步获取。然而我的循环变量与异步获取的数据有关!那么循环代码要怎么写呢?
下面是我用递归写的代码,不过处理得很慢。。这是demo,可以输入tj试一下,很慢的。
let starredLists = []
!function getStarred(index){
axios.get(`/users/${app.userName}/starred?page=${index++}&per_page=100`)
.then(function(response){
starredLists.push(...response.data)console.log(starredLists.length + ' ' + index)if(response.data.length == 100)
getStarred(index);if(response.data.length != 100)
app.stars = starredLists.length;
})
}(1)
回答
一定要循环么 用递归请求呗
你可以用Promise.all
//get user's starred repos //get user's starred repos let starredLists = [],
rq = [];
axios.defaults.baseURL = 'https://api.github.com';for(let i = 1;i < 10; i++){
rq.push(axios.get(`/users/tj/starred?page=${i}&per_page=100`)
.then(function (response) { if(response.data.length == 0) break;
starredLists.push(...response.data) console.log('starredLists.length: '+ starredLists.length)
}));
}Promise.all(rq).then(() => { // 理想状态下,请求全部成功!
app.stars = starredLists.length
}).finally(() => { // 这个属性 不管 then 还是 catch 必定进入
// 可能请求失败了!
if(!app.stars) {
app.stars = starredLists.length
}
});
用了递归的方式,解决了循环变量无法确定的问题;
同时为了性能,用Promise.all()做了批量请求。卖QQ号码平台地图获取3个组10个接口(以tj大神的star为例)需要大约10s
//get user's starred repos let starredLists = [];let promiseTen = [],
promiseOne;
!function getStarred(index) { //用for循环,一次性请求十个接口,加快速度,避免同步-异步-同步的反复切换
for (let i = 0; i < 10; i++) {
promiseOne = axios.get(`/users/${app.userName}/starred?page=${index++}&per_page=100`)
.then(function (response) {
starredLists.push(...response.data)
})
promiseTen.push(promiseOne)
} Promise.all(promiseTen).then(() => { if(starredLists.length % 100 == 0) //检查是否需要递归
getStarred(index)
else
app.stars = starredLists.length
})
}(1)