作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试编写一个从 API 检索所有用户数据的函数。不幸的是,API 每次请求只返回 50 条数据。为了检索结果的下一个“页面”,需要发出另一个 GET 请求,并使用一个额外的路径指示结果页面。
(在我的例子中,API 是 Imgur,数据片段是用户的相册。)
我正在尝试使用 Promises 来做到这一点。函数 populateAlbumList 成功返回仅结果的第一页。
我试图修改它以在函数 populateAlbumList2 中获得更多页的结果,但它无法正常工作。
如何让这些有条件的嵌套 promise 发挥作用? (我不想使用像 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());
}
})
);
}
}
最佳答案
由于您使用的是 async
函数,因此您无需直接处理 promises,只需使用 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 在我贫血的小博客上)。
关于javascript - 未知数量的 promise 取决于先前 promise 的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53177600/
我是一名优秀的程序员,十分优秀!