如何对 Github 上的用户的所有存储库发出一个异步请求
How to make one async request for all repositories of a user on Github
以下大概就是我需要做的事情了。但这是写在 Python 中的,我没有掌握一些细节:
How to get all repositories of a specific GitHub user.
到目前为止,这是我的代码:
function loadRepositories() {
let arrOfRepos = []
for (var i = 1, j = 1; j > 0; i++) {
var req = new XMLHttpRequest();
// must be synchronous or else, j is assigned below, before the response is received from send(). While send() is going on, j is assigned the value of the empy responseText. And the loop doesn't continue.
req.open('GET', 'https://api.github.com/users/-user-/repos?page=' + i, false)
req.send()
arrOfRepos = arrOfRepos.concat(JSON.parse(req.responseText))
var j = JSON.parse(req.responseText).length
}
showRepositories(arrOfRepos)
}
我只想以某种方式向 URL 提出一个请求。似乎使用分页的唯一方法是多次联系 URL,然后测试我是否应该再打一个电话。
我试图在 showRepositories()
中测试 req
的 links
键,但是 this.links
returns undefined
.
我的作品有效,但它非常缓慢且丑陋。有没有一种方法可以调用 API 并更快地构建我的单独响应?
一种方法是使用 Promise
and wait for all the promises to resolve with Promise.all
。您将必须进行一次初始调用以获取 Link
header 并检查最后一页是什么。然后进行 (number_of_page - 1) 异步调用(在回调函数中获取响应)。
var url = "https://api.github.com/users/google/repos?per_page=100";
var repos = [];
function sendRequest(url, parseLink) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var resp = xhr.responseText;
var respJson = JSON.parse(resp);
if (parseLink) {
resolve(getLastPage(xhr.getResponseHeader("Link")), respJson);
} else {
resolve(respJson);
}
} else {
reject(xhr.status);
}
}
}
});
}
function getLastPage(link) {
if (link) {
var linkArr = link.split(',');
for (var i = 0; i < linkArr.length; i++) {
if (linkArr[i].indexOf('rel="last"') != -1) {
return new URL(linkArr[i].substring(linkArr[i].lastIndexOf("<") + 1, linkArr[i].lastIndexOf(">"))).searchParams.get('page');
}
}
}
return 1;
}
sendRequest(url, true).then(function(lastPage, data) {
console.log("last page is " + lastPage);
repos = repos.concat(data);
var requests = [];
if (lastPage > 1) {
for (var i = 2; i < parseInt(lastPage) + 1; i++) {
requests.push(sendRequest(url + "&page=" + i).then(function(data) {
repos = repos.concat(data);
}));
}
Promise.all(requests).then(function(data) {
console.log("all promises have been resolved, total repo count : " + repos.length);
})
.catch(function(err) {
console.log('Error executing promisses', err);
});
} else {
console.log("only 1 request was necessary, total repo count : " + repos.length);
}
});
在上面的代码片段中,每次解决一个承诺时,结果都会连接到 repos
数组,一旦解决了所有承诺,您就可以处理您的数据。
请注意,您可以使用 per_page=100
到 return 每个请求最多 100 个存储库,而不是默认的 30 个。
以下大概就是我需要做的事情了。但这是写在 Python 中的,我没有掌握一些细节: How to get all repositories of a specific GitHub user.
到目前为止,这是我的代码:
function loadRepositories() {
let arrOfRepos = []
for (var i = 1, j = 1; j > 0; i++) {
var req = new XMLHttpRequest();
// must be synchronous or else, j is assigned below, before the response is received from send(). While send() is going on, j is assigned the value of the empy responseText. And the loop doesn't continue.
req.open('GET', 'https://api.github.com/users/-user-/repos?page=' + i, false)
req.send()
arrOfRepos = arrOfRepos.concat(JSON.parse(req.responseText))
var j = JSON.parse(req.responseText).length
}
showRepositories(arrOfRepos)
}
我只想以某种方式向 URL 提出一个请求。似乎使用分页的唯一方法是多次联系 URL,然后测试我是否应该再打一个电话。
我试图在 showRepositories()
中测试 req
的 links
键,但是 this.links
returns undefined
.
我的作品有效,但它非常缓慢且丑陋。有没有一种方法可以调用 API 并更快地构建我的单独响应?
一种方法是使用 Promise
and wait for all the promises to resolve with Promise.all
。您将必须进行一次初始调用以获取 Link
header 并检查最后一页是什么。然后进行 (number_of_page - 1) 异步调用(在回调函数中获取响应)。
var url = "https://api.github.com/users/google/repos?per_page=100";
var repos = [];
function sendRequest(url, parseLink) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var resp = xhr.responseText;
var respJson = JSON.parse(resp);
if (parseLink) {
resolve(getLastPage(xhr.getResponseHeader("Link")), respJson);
} else {
resolve(respJson);
}
} else {
reject(xhr.status);
}
}
}
});
}
function getLastPage(link) {
if (link) {
var linkArr = link.split(',');
for (var i = 0; i < linkArr.length; i++) {
if (linkArr[i].indexOf('rel="last"') != -1) {
return new URL(linkArr[i].substring(linkArr[i].lastIndexOf("<") + 1, linkArr[i].lastIndexOf(">"))).searchParams.get('page');
}
}
}
return 1;
}
sendRequest(url, true).then(function(lastPage, data) {
console.log("last page is " + lastPage);
repos = repos.concat(data);
var requests = [];
if (lastPage > 1) {
for (var i = 2; i < parseInt(lastPage) + 1; i++) {
requests.push(sendRequest(url + "&page=" + i).then(function(data) {
repos = repos.concat(data);
}));
}
Promise.all(requests).then(function(data) {
console.log("all promises have been resolved, total repo count : " + repos.length);
})
.catch(function(err) {
console.log('Error executing promisses', err);
});
} else {
console.log("only 1 request was necessary, total repo count : " + repos.length);
}
});
在上面的代码片段中,每次解决一个承诺时,结果都会连接到 repos
数组,一旦解决了所有承诺,您就可以处理您的数据。
请注意,您可以使用 per_page=100
到 return 每个请求最多 100 个存储库,而不是默认的 30 个。