[英]Node fetch loop too slow
我有一個 API js 文件,我用 POST 方法調用它,傳入一個對象數組,每個對象包含一個站點 url(大約 26 個對象或 url)作為正文,並使用下面的代碼循環遍歷這個數組( sites
) , 檢查每個對象 url 是否通過向 url 添加"/items.json"
返回 json,如果是,則將 json 內容推siteLists
我作為響應發送回的另一個最終數組siteLists
中。
問題是只有 26 個 url,這個 API 調用需要超過5 秒才能完成,我是否以錯誤的方式進行了操作,或者這只是 Node.js 中fetch
工作方式?
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()
}
我在這里看到的最大問題是,在循環啟動下一個fetch
請求之前,您似乎在await
一次fetch
完成,從而有效地連續運行它們。 如果您重寫腳本以同時並行運行所有請求,則可以將每個請求按順序推送到Promise.all
,然后在結果返回時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)
)
);
雖然await
是一種很好的糖,但有時最好堅持使用then
export default async (req, res) => {
if (req.method === 'POST') {
const body = JSON.parse(req.body)
const sites = body.list // this content shown above
const siteListsPromises = []
if (sites?.length > 0){
var b=0
while (b < sites.length){
let url = sites?.[b]?.url
if (url) {
let jurl = `${url}/items.json`
// #1
const promise = fetch(jurl)
// #2
.then(async (fUrl) => {
let siteData = await fUrl.json()
if (siteData){
...
return {
// #3
id: -1,
name: name,
label: label,
items: items
}
}
})
// #4
.catch(err => {
// console.log(err)
})
siteListsPromises.push(promise)
}
b++
}
}
// #5
const siteLists = (await Promise.all(siteListsPromises))
// #6
.filter(el => el !== undefined)
// #7
.map((el, i) => el.id = i)
res.send({ sites: siteLists })
}
res.end()
}
在代碼段中查找// #N
注釋。
await
請求完成。 而是遍歷sites
並一次發送所有請求json()
和siteData
處理后的fetch
與then
。 如果您對siteData
的處理計算量更大,那么這樣做會更有意義,而不是在所有承諾解決后才執行所有操作。siteData
元素的id
。 我不會深入探討這個問題,但會進一步解決它。.catch()
而不是try{}catch(){}
。 因為沒有await
它不會工作。Promise.all()
await
所有請求的結果siteData
為假的id
字段。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.