Sonatype REST API將其回應中的資料分頁,并continuation token放置在回應正文中;如果繼續標記是null,您就知道您在結果的最后一頁。
我想遞回地從端點獲取所有記錄fetch(除非有更好的策略?),在每次遞回迭代中使用查詢引數更新 url 并fetch在其上呼叫遞回,并構建一個包含完整串列的存盤結構函式中的記錄。我一直不成功。
要獲取記錄的第一頁,這是有效的:
const requestUrl = `https://{baseURL}/service/rest/v1/components?repository=myRepo&group=myGroup`;
// returns first 10 results
async function fetchData(url) {
let headers = new Headers();
headers.append("Accept", "application/json");
headers.append(
"Authorization",
"Basic <BASE64-STRING-HERE>"
);
const requestOptions = {
method: "GET",
headers: headers,
redirect: "follow",
};
// Fetch request and parse as JSON
const response = await fetch(url, requestOptions);
let data = await response.json();
return data;
}
// called at `/api/get-data`
export default async function getData(req, res) {
try {
let result = await fetchData(requestUrl);
res.status(200).json({ result });
} catch (err) {
res.status(500).json({ error: "failed to load data" });
}
}
這將回傳一個物件,其中包含一個包含 10 條記錄的陣列和continuation token一個字串,例如
{"items":[{"id": 1, "name": "itemOne"}, {"id": 2, "name": "itemTwo"}, etc.],"continuationToken":"07929bf0c78cf6c92d4acd0bf5823d80"}}
在記錄的最后一頁,continuationToken是null:
{"items":[{"id": 99, "name": "itemNinetyNine"}, {"id": 100, "name": "itemOneHundred"}, etc.],"continuationToken": null}}
要使用遞回獲取完整的記錄集,這是我嘗試過的策略,但沒有成功:
async function recursivelyFetchData(url) {
let headers = new Headers();
headers.append("Accept", "application/json");
headers.append(
"Authorization",
"Basic <BASE-64-STRING>"
);
const requestOptions = {
method: "GET",
headers: headers,
redirect: "follow",
};
try {
// Fetch request and parse as JSON
const response = await fetch(url, requestOptions);
let data = await response.json();
// create a storage array
let storage = [];
// Set a variable for the next page url
let nextPageUrl;
// if the initial response contains a continuation token, start to recurse
if (data.continuationToken) {
// remove the query param so we don't keep adding it to the url string on each iteration
let strippedUrl = url.replace(/&continuationToken=.*/g, "");
// create the url with the query param
nextPageUrl =
strippedUrl `&continuationToken=` data.continuationToken;
// store the next response
let nextPageResponse = await recursivelyFetchData(
nextPageUrl,
requestOptions
);
// parse
let nextPageData = await nextPageResponse.json();
// add to storage
storage = [...data, ...nextPageData.items];
}
// break recursion
return storage;
} catch (err) {
res.status(500).json({ error: "failed to load data" });
}
}
export default async function getData(req, res) {
try {
let result = await recursivelyFetchData(requestUrl);
res.status(200).json({ result });
} catch (err) {
res.status(500).json({ error: "failed to load data in getPackages" });
}
}
我已經嘗試過在此處、此處、此處、此處和此處找到的方法,但是此 API 與其他分頁回應不同,因為它依賴于回應正文中的延續標記,而我這輩子都做不到弄清楚如何遞回地將查詢引數添加到 url,繼續迭代直到繼續令牌為null,然后中斷遞回。
任何幫助表示贊賞。
uj5u.com熱心網友回復:
這是我認為是一種簡單的方法。 fetchAllPages獲取第一頁,然后檢查結果是否具有非零continuation標記。如果不是,我們只回傳結果中的專案。但如果是這樣,我們將該標記合并到一個新的 url 中并重復出現,將當前項與新獲取的項合并到一個陣列中。
依賴于addToken構建我們的 URL 的輔助函式,它看起來像這樣:
const fetchAllPages = (url) => fetch (url)
.then (res => res .json ())
.then (
({items, continuationToken: token}) => token
? fetchAllPages (addToken (url, token)) .then (newItems => [...items, ...newItems])
: items
)
我們稍微改變它以顯示您的標題操作等適合的位置,在一個使用fetch回傳的虛擬函式的片段中item0-item33以十個為一組進行分頁,addToken并使用 DOM 方法(而不是字串決議/黑客攻擊)進行 URL 操作的實作:
const addToken = (base, token) => {
const url = new URL (base)
const searchParams = new URLSearchParams (url .search)
searchParams .set ('continuationToken', token)
url .search = searchParams
return url .toString ()
}
const fetchAllPages = (url) => {
// configure fetch parameters (headers, etc.)
return fetch (url, /*headers, whatever*/)
.then (res => res .json ())
.then (
({items, continuationToken: token}) => token
? fetchAllPages (addToken (url, token)) .then (newItems => [...items, ...newItems])
: items
)
}
fetchAllPages ('https://baseURL.com/service/rest/v1/components?repository=myRepo&group=myGroup')
.then (console .log)
.catch (console .warn)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script>
// dummy version of `fetch` to demo without a real server
const fetch = (() => {
const data = Array .from ({length: 34}, (_, id) => ({id, name: `item ${id}`}))
const pageSize = 10
return async (s) => {
console .log (`fetching '${s}'`)
const url = new URL (s)
const searchParams = new URLSearchParams (url .search)
const start = searchParams .get ('continuationToken') || '0'
const startIndex = data .findIndex (({id}) => id == start)
const token = startIndex < 0 || (startIndex pageSize >= data.length) ? null : data [startIndex pageSize] .id
return {json: () => ({
items: data .slice (startIndex, startIndex pageSize),
continuationToken: token ? String (token) : null
})}
}
})()
</script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/490992.html
標籤:javascript 节点.js 递归 获取 API
下一篇:如何有效地提取字串中的實體值
