我正在尝试编写一个从API检索用户所有数据的函数。不幸的是,该API每个请求仅返回50条数据。为了检索结果的下一个“页面”,需要发出另一个GET请求,并带有一个额外的路径来指示结果页面。
(在我的情况下,API是Imgur,数据段是用户的相册。)
我正在用Promises做到这一点。函数populateAlbumList成功返回仅结果的第一页。
我试图对其进行修改,以在函数populateAlbumList2中获得更多页面的结果,但是它无法正常工作。
如何使这些有条件嵌套的诺言起作用? (我不想使用像bluebird / q这样的库,因为我想了解概念和模式本身。)
/**
* Performs an AJAX get request to the Imgur API, retrieving all the albums owned by the user. When the albums are
* populated, they are logged to the extension settings page's console.
* @returns {Promise<void>}
*/
async function populateAlbumList() {
const username = await getItemFromStorage(STORAGE_USERNAME, ERROR_STORAGE_USERNAME_NOT_FOUND);
const ALBUMS_URL = `https://api.imgur.com/3/account/${username}/albums`;
// Fetch the albums for the currently logged in user
return fetch(ALBUMS_URL, {
method: "GET",
headers: {
"Authorization": "Bearer " + CLIENT_ID,
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => json.data)
.then(albums => albums.forEach(album => addAlbumToPage(album)));
}
/**
* Performs an AJAX get request to the Imgur API, retrieving all the albums owned by the user. When the albums are
* populated, they are logged to the extension settings page's console.
* @returns {Promise<Array>}
*/
async function populateAlbumList2() {
const username = await getItemFromStorage(STORAGE_USERNAME, ERROR_STORAGE_USERNAME_NOT_FOUND);
let ALBUMS_URL = `https://api.imgur.com/3/account/${username}/albums`;
const allAlbums = [];
let page = 0;
const promises = [];
await getAlbumsFromImgur()
.then(() => console.log(allAlbums));
function getAlbumsFromImgur() {
if (page > 0) {
ALBUMS_URL = `https://api.imgur.com/3/account/${username}/albums` + page;
}
promises.push(
fetch(ALBUMS_URL, {
method: "GET",
headers: {
"Authorization": "Bearer " + CLIENT_ID,
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => json.data)
.then(albums => {
allAlbums.push(albums);
if (albums.length >= 50) {
page++;
promises.push(getAlbumsFromImgur());
}
})
);
}
}
答案 0 :(得分:1)
由于您正在使用async
函数,因此您无需直接处理承诺,只需使用await
并编写逻辑流程即可。首先,让我们将其应用于仅获得第一页,以便我们可以看到它如何简化了功能;查看***
注释:
async function populateAlbumList() {
const username = await getItemFromStorage(STORAGE_USERNAME, ERROR_STORAGE_USERNAME_NOT_FOUND);
const ALBUMS_URL = `https://api.imgur.com/3/account/${username}/albums`;
// Fetch the albums for the currently logged in user
// *** Use await to consume the promise
const response = await fetch(ALBUMS_URL, {
method: "GET",
headers: {
"Authorization": "Bearer " + CLIENT_ID,
"Content-type": "application/json; charset=UTF-8"
}
});
// Note: You have to check for errors
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
// Read and parse the JSON, get the `data` property from it using destructuring
// *** Use await to consume the promise
let { data: albums } = await response.json();
// Add the albums; no need for `forEach` when we have `for-of` available to us
for (const album of albums) {
addAlbumToPage(album);
}
}
现在让我们扩展该功能,以便它继续对后续页面进行请求,直到返回少于50个结果:
async function populateAlbumList() {
const username = await getItemFromStorage(STORAGE_USERNAME, ERROR_STORAGE_USERNAME_NOT_FOUND);
const ALBUMS_URL = `https://api.imgur.com/3/account/${username}/albums`;
// Start on page 0
let page = 0;
let albums; // We'll need this in our while condition below
do {
// Fetch the albums for the currently logged in user,
// adding in the page if page > 0
const response = await fetch(
page === 0 ? ALBUMS_URL : ALBUMS_URL + page, // Seems odd there's no `/` or `?page=` or similar
{
method: "GET",
headers: {
"Authorization": "Bearer " + CLIENT_ID,
"Content-type": "application/json; charset=UTF-8"
}
}
);
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
// Read and parse the JSON, get the `data` from it
albums = (await response.json()).data;
// Add the albums
for (const album of albums) {
addAlbumToPage(album);
}
++page;
// Keep going until we get fewer than 50 back
} while (albums.length >= 50);
}
请注意,我还添加了一个检查以查看fetch
是否有效,这是您的原始代码所缺少的。不仅仅是您,大多数人们忘记了包括那张支票(以至于我wrote it up出现在我贫乏的小博客上)。