发出 http 请求然后可能发出另一个请求的最佳方法
Best way to make a http request and then potentially another one
标题不是很清楚,但要详细说明,我需要向 API 端点发出 HTTP 请求,到目前为止,我使用的函数看起来像这样:
function getPostsFromAPI(argOne, argTwo) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
apiGet(`${apiUrl}?name=argOne&something=argTwo`).then(userPosts => {
// do stuff with userPosts
return userPostData
}).catch(handleError)
}
但是,API 响应可以包括以下内容:
{
//...
"has_more": true,
"next_offset": 10
}
在这种情况下,我需要再次发送 API 调用,这次使用 &offset=10
参数。
Promise 需要继续进行 API 调用,直到 has_more: true
不再存在。我最初的想法是仅 re-run getPostsFromAPI()
基于内部的 if 语句,但我无法弄清楚如何使它在承诺中干净利落地工作。最终,promise 应该继续发出请求,直到 API 说它 运行 没有数据可以提供(我将实施我自己的限制)。
实现此目标的最佳方法是什么?
如果使用 async
/await
,实现此目的的算法会更加明显。您可以只创建一个空数组,然后在循环中逐渐附加到它,直到服务器指示没有更多结果。
async function getPostsFromAPI(argOne, argTwo) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
let results = [];
let offset = 0;
while (true) {
let response = await apiGet(`${apiUrl}?name=argOne&something=argTwo&offset=${offset}`);
results = results.concat(response.records);
if (response.has_more) {
offset = response.next_offset;
} else {
return results;
}
}
}
如果您不能使用 async
/await
并且必须遵守承诺,您可以使用递归让方法在每次响应指示有更多记录时调用自身:
function getPostsFromAPI(argOne, argTwo) {
return new Promise((resolve, reject) => {
const apiUrl = `https://www.exampleapi.com/v1/userposts`;
let results = [];
let offset = 0;
const getNextPage = (offset = 0) => {
apiGet(`${apiUrl}?name=argOne&something=argTwo&offset=${offset}`).then((response) => {
results = results.concat(response.records);
if (response.has_more) {
getNextPage(response.next_offset);
} else {
resolve(results);
}
}).catch(reject);
}
getNextPage(0);
});
}
请注意,作为一般的良好做法,您永远不应通过连接或模板字符串构造查询字符串。您应该使用 URLSearchParams.toString()
来确保您的查询字符串被正确编码。您可以通过创建一个新的 URL
:
来间接执行此操作
const url = new URL(`https://www.exampleapi.com/v1/userposts`)
url.searchParams.append("argOne", argOne);
url.searchParams.append("argTwo", argTwo);
url.searchParams.append("offset", offset);
url.toString()
这是 async generator 的一个很好的用例。
看起来像下面这样
async function* getPostsFromAPI(arg1, arg2) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
let response = { next_offset: 0 };
do {
response = await apiGet(`${apiUrl}?name=${arg1}&something=${arg2}&offset=${response.next_offset}`)
response.items.forEach((item) => {
yield item
})
} while (response.has_more)
}
标题不是很清楚,但要详细说明,我需要向 API 端点发出 HTTP 请求,到目前为止,我使用的函数看起来像这样:
function getPostsFromAPI(argOne, argTwo) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
apiGet(`${apiUrl}?name=argOne&something=argTwo`).then(userPosts => {
// do stuff with userPosts
return userPostData
}).catch(handleError)
}
但是,API 响应可以包括以下内容:
{
//...
"has_more": true,
"next_offset": 10
}
在这种情况下,我需要再次发送 API 调用,这次使用 &offset=10
参数。
Promise 需要继续进行 API 调用,直到 has_more: true
不再存在。我最初的想法是仅 re-run getPostsFromAPI()
基于内部的 if 语句,但我无法弄清楚如何使它在承诺中干净利落地工作。最终,promise 应该继续发出请求,直到 API 说它 运行 没有数据可以提供(我将实施我自己的限制)。
实现此目标的最佳方法是什么?
如果使用 async
/await
,实现此目的的算法会更加明显。您可以只创建一个空数组,然后在循环中逐渐附加到它,直到服务器指示没有更多结果。
async function getPostsFromAPI(argOne, argTwo) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
let results = [];
let offset = 0;
while (true) {
let response = await apiGet(`${apiUrl}?name=argOne&something=argTwo&offset=${offset}`);
results = results.concat(response.records);
if (response.has_more) {
offset = response.next_offset;
} else {
return results;
}
}
}
如果您不能使用 async
/await
并且必须遵守承诺,您可以使用递归让方法在每次响应指示有更多记录时调用自身:
function getPostsFromAPI(argOne, argTwo) {
return new Promise((resolve, reject) => {
const apiUrl = `https://www.exampleapi.com/v1/userposts`;
let results = [];
let offset = 0;
const getNextPage = (offset = 0) => {
apiGet(`${apiUrl}?name=argOne&something=argTwo&offset=${offset}`).then((response) => {
results = results.concat(response.records);
if (response.has_more) {
getNextPage(response.next_offset);
} else {
resolve(results);
}
}).catch(reject);
}
getNextPage(0);
});
}
请注意,作为一般的良好做法,您永远不应通过连接或模板字符串构造查询字符串。您应该使用 URLSearchParams.toString()
来确保您的查询字符串被正确编码。您可以通过创建一个新的 URL
:
const url = new URL(`https://www.exampleapi.com/v1/userposts`)
url.searchParams.append("argOne", argOne);
url.searchParams.append("argTwo", argTwo);
url.searchParams.append("offset", offset);
url.toString()
这是 async generator 的一个很好的用例。
看起来像下面这样
async function* getPostsFromAPI(arg1, arg2) {
const apiUrl = `https://www.exampleapi.com/v1/userposts`
let response = { next_offset: 0 };
do {
response = await apiGet(`${apiUrl}?name=${arg1}&something=${arg2}&offset=${response.next_offset}`)
response.items.forEach((item) => {
yield item
})
} while (response.has_more)
}