Está en mi UserScript. El resaltado de sintaxis para typescript no funciona; y js funciona de forma extraña. Debería ser javascript. Tanto ts como typescript funcionan en StackOverflow, sin embargo.
interface IPost {
id: number
username: string
post_number: number
cooked: string
}
interface ITopicResponse {
actions_summary: {}[]
archetype: string
fancy_title: string
title: string
post_stream: {
posts: IPost[]
stream: number[]
}
posts_count: number
reply_count: number
}
export async function jsonFetch<T>(url: string): Promise<T | null> {
const r = await fetch(url)
if (r.ok) {
const json = await r.json()
if (!json.errors) {
return json
}
}
logger('error', r)
return null
}
export async function fetchAll(urlBase: string) {
const r0 = await jsonFetch<ITopicResponse>(urlBase + '.json?print=true')
if (!r0) return []
const posts: IPost[] = r0.post_stream.posts
let page = 2
while (posts.length < r0.posts_count) {
const r = await jsonFetch<ITopicResponse>(
urlBase + '.json?print=true&page=' + page++
)
if (!r || !r.post_stream.posts.length) {
break
}
posts.push(...r.post_stream.posts)
await new Promise((resolve) => setTimeout(resolve, 1000))
}
return posts
}
fetchAll('https://community.wanikani.com/t/16404').then(console.log)
En un script de ts-node usando Axios,
(node:1102374) UnhandledPromiseRejectionWarning: Error: Request failed with status code 422
Si espero lo suficiente, como 10 minutos, fallará en la página 2; pero si repito ahora, no puedo cargar ninguna URL.
Y sin print funciona bien.
De hecho, logré que funcionara evitando print=true.
export async function fetchAll(urlBase: string) {
const r0 = await jsonFetch<ITopicResponse>(urlBase + '.json');
if (!r0) return [];
const stream = r0.post_stream.stream || [];
const chunks: number[][] = [];
while (stream.length) {
chunks.push(stream.splice(0, 300));
}
const posts: IPost[] = [];
let isContinue = true;
while (chunks.length && isContinue) {
const rs = await Promise.all(
chunks
.splice(0, 10)
.map((ids) =>
jsonFetch<ITopicPostResponse>(
urlBase +
'/posts.json?' +
ids.map((id) => `post_ids[]=${id}`).join('&'),
),
),
).then((rs) =>
rs.map((r) => {
if (!r) {
isContinue = false;
return [];
}
return r.post_stream.posts;
}),
);
rs.map((r) => {
posts.push(...r);
});
if (chunks.length) {
await new Promise((r) => setTimeout(r, 1000));
}
}
posts.push(...r0.post_stream.posts);
if (!isContinue) {
logger(
'error',
`Total posts: ${r0.posts_count} != real count: ${posts.length}, due to Rate Limit?`,
);
}
return posts;
}