javascript - 节点获取循环太慢
问题描述
我有一个 API js 文件,我用 POST 方法调用它,传入一个对象数组,每个对象都包含一个站点 url(大约 26 个对象或 url)作为主体,并使用下面的代码循环遍历这个数组(sites
),检查每个对象 url 是否通过添加到 url 来返回一个 json "/items.json"
,如果是,则将 json 内容推送到另一个siteLists
我作为响应发回的最终数组中。
问题是只有 26 个 url,这个 API 调用需要超过5 秒才能完成,我做错了还是它只是fetch
在 Node.js 中工作的方式?
const sites
内容看起来像:
[{label: "JonLabel", name: "Jon", url: "jonurl.com"},{...},{...}]
代码是:
export default async (req, res) => {
if (req.method === 'POST') {
const body = JSON.parse(req.body)
const sites = body.list // this content shown above
var siteLists = []
if (sites?.length > 0){
var b=0, idd=0
while (b < sites.length){
let url = sites?.[b]?.url
if (url){
let jurl = `${url}/items.json`
try {
let fUrl = await fetch(jurl)
let siteData = await fUrl.json()
if (siteData){
let items = []
let label = sites?.[b]?.label || ""
let name = sites?.[b]?.name || ""
let base = siteData?.items
if(base){
var c = 0
while (c < base.length){
let img = base[c].images[0].url
let titl = base[c].title
let obj = {
url: url,
img: img,
title: titl
}
items.push(obj)
c++
}
let object = {
id: idd,
name: name,
label: label,
items: items
}
siteLists.push(object)
idd++
}
}
}catch(err){
//console.log(err)
}
}
b++
}
res.send({ sites: siteLists })
}
res.end()
}
编辑:(解决方案?)
因此,似乎带有如下建议的承诺并标记为解决方案的代码在更快的意义上工作,有趣的是它仍然需要超过 5 秒才能加载并且仍然抛出Failed to load resource: the server responded with a status of 504 (Gateway Time-out)
错误,因为Vercel,托管应用程序的无服务器功能的最大超时为 5 秒,因此永远不会在响应中加载内容。在本地,我没有超时限制的地方加载速度明显更快,但令我惊讶的是,这样的查询需要这么长时间才能完成,而它应该是毫秒的问题。
解决方案
await
我在这里看到的最大问题是,fetch
在循环开始下一个请求之前,您似乎要完成一个,有效地串行fetch
运行它们。如果您重写脚本以同时并行运行所有请求,则可以将每个请求按顺序推送到 a中,然后在它们返回时处理结果。Promise.all
可以这样想——如果每个请求需要一秒钟才能完成,而您有 26 个请求,并且您在开始下一个请求之前等待一个请求完成,则总共需要 26 秒。但是,如果您将它们全部一起运行,如果它们仍然只需要一秒钟来完成整个事情,则只需一秒钟。
伪代码中的一个例子——
你想改变这个:
const urls = ['url1', 'url2', 'url3'];
for (let url of urls) {
const result = await fetch(url);
process(result)
}
...进入这个:
const urls = ['url1', 'url2', 'url3'];
const requests = [];
for (let url of urls) {
requests.push(fetch(url));
}
Promise.all(requests)
.then(
(results) => results.forEach(
(result) => process(result)
)
);
推荐阅读
- kubernetes-helm - Helm Charts:如何在 K0s 集群中安装包?
- node.js - 如何在heroku上成功部署
- python - Selenium 没有点击 cookie 接受按钮
- r - 将数据帧列表中每个数据帧中所有出现的 NaN 更改为另一个值
- seaborn - 如何获得正确的seaborn直方图?
- swift - PEM 公共文件转换为字符串 [Swift]
- css - 嘿,我不知道在这种情况下如何使用 ::after 。CSS
- grails - Grails 包绕过证书
- flutter - 我如何使用 runZoned 知道错误来自哪个页面?
- java - 我无法遍历父窗口到子窗口