我的 JavaScript 代码中有一个函数,它循环遍历数组并对数组的每个项目执行一些耗时的操作。当数组中的项目数量较少时,它目前工作正常,但我也希望代码在数组较大时也能工作。这是我的功能:
const fetchAndProcessNews = async (queryString, from) => {
const query = {
queryString,
from,
size: 1,
}
try {
console.log('Fetching news...')
const { articles } = await searchApi.getNews(query)
console.log('total articles fetched:', articles.length)
console.log('Fetched news:', articles)
if (articles && articles.length > 0) {
console.log('Processing news...')
//looping through all the articles fetched from api
for (const article of articles) {
console.log('Processing article with name: ', article.title)
const { title, sourceUrl, id, publishedAt } = article
//scraping content from the source url and returning the markup of the single article
const markup = await scraper(sourceUrl)
//using gpt to perform some tasks on the markup returned from scrapping
const data = await askGpt(markup)
//using dall e to generate an image
const generatedImageUrl = await generateImg(data?.imageDescription)
//downloading the image from the url and uploading it to s3
const s3ImageUrl = await generateImgUrl(generatedImageUrl, title, id)
//uploading the article to strapi using post request
const newTitle = data?.title
const newMarkup = data?.content
const description = data?.abstract
const categories = data?.categories
console.log('pushing article to strapi')
await createPost(
newTitle,
description,
newMarkup,
s3ImageUrl,
publishedAt,
categories
)
console.log('article processsing completed...')
}
} else {
console.log('No articles found')
}
} catch (error) {
console.error('Error fetching news:', error.message)
}
}
让我解释一下我在做什么,我从 api 获取一些新闻文章,并且对于每一篇文章我都会执行这些任务:
现在我担心如果文章数量是 100 或 1000,这段代码将如何工作?它能够处理所有这些耗时的任务吗?如何使其更加优化,使其不崩溃并正常工作?我没有那么多经验,所以我有点担心。我应该使用什么技术?我应该使用某种队列,如 bull js 或批处理吗?如果有人可以提供详细的答案,这将是一个很大的帮助。
这个想法是不要等到文章处理的所有步骤完成才开始处理下一篇文章。
例如,您可以每隔 100 毫秒开始阅读下一篇文章。您甚至可以立即启动它们,但风险是您可能会向同一服务器发出太多请求,从而达到某些服务器限制。因此,在文章处理启动之间稍微延迟可能更为谨慎。要获得这样的中间延迟,您可以使用这个通用函数:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
实现整体想法的最简单方法是将文章处理的代码放在单独的函数中:
const processArticle = async (article) = {
console.log('Processing article with name: ', article.title)
const { title, sourceUrl, id, publishedAt } = article
//scraping content from the source url and returning the markup of the single article
const markup = await scraper(sourceUrl)
//using gpt to perform some tasks on the markup returned from scrapping
const data = await askGpt(markup)
//using dall e to generate an image
const generatedImageUrl = await generateImg(data?.imageDescription)
//downloading the image from the url and uploading it to s3
const s3ImageUrl = await generateImgUrl(generatedImageUrl, title, id)
//uploading the article to strapi using post request
const newTitle = data?.title
const newMarkup = data?.content
const description = data?.abstract
const categories = data?.categories
console.log('pushing article to strapi')
await createPost(
newTitle,
description,
newMarkup,
s3ImageUrl,
publishedAt,
categories
)
console.log('article processing completed...')
};
此处没有更改代码;它刚刚被转移到一个函数中。
现在您的主函数可以执行上述函数而无需等待。相反,它可以捕获它返回的承诺(将处于待处理状态),并将此类承诺收集在数组中。这意味着现在将对不同的文章提出多个请求,而无需等待他们的回复。最后,您可能希望等待所有这些承诺都已解决。
这是你原来的函数的样子:
const fetchAndProcessNews = async (queryString, from) => {
const query = {
queryString,
from,
size: 1,
}
try {
console.log('Fetching news...')
const { articles } = await searchApi.getNews(query)
console.log('total articles fetched:', articles.length)
console.log('Fetched news:', articles)
if (articles && articles.length > 0) {
console.log('Processing news...')
// looping through all the articles fetched from api
const promises = [];
for (const article of articles) {
promises.push(processArticle(article)); // We don't await!
await delay(100); // Determine which delay is suitable
}
// All articles are now being processed; wait for all to finish (optional)
await promise.allSettled(promises);
} else {
console.log('No articles found')
}
} catch (error) {
console.error('Error fetching news:', error.message)
}
}
await Promise.allSettled
操作是可选的,但它对于 fetchAndProcessNews
的调用者很有用,因为只有在所有操作完成后,他们得到的承诺才会得到解决。