Javascript 如何在串行中列出一长串http调用?
我试图一次只进行一次http调用,但当我记录来自Javascript 如何在串行中列出一长串http调用?,javascript,node.js,ecmascript-5,ecmascript-2016,Javascript,Node.js,Ecmascript 5,Ecmascript 2016,我试图一次只进行一次http调用,但当我记录来自getUrl的响应时,它们正在堆积,我开始收到409(太多请求) 基本上,我不希望在前一个http完成之前启动下一个http。否则我就砸了他们的服务器 奖励点:同时使用5个。因为您使用的是等待,所以在任何地方使用它都会比使用混淆的容易得多。然后使用减少。避免这种情况也很好。这应该满足您的要求: const results = []; for (const url of urls) { const response = await fetch(u
getUrl
的响应时,它们正在堆积,我开始收到409(太多请求)
基本上,我不希望在前一个http完成之前启动下一个http。否则我就砸了他们的服务器
奖励点:同时使用5个。因为您使用的是
等待
,所以在任何地方使用它都会比使用混淆的容易得多。然后使用减少。避免这种情况也很好。这应该满足您的要求:
const results = [];
for (const url of urls) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(response); // or whatever logic you need with errors
}
results.push(await response.text());
}
let mapped;
for (u of urls) {
mapped.push(await doFetch(u));
}
然后,您的结果
变量将包含一个响应文本数组(或者抛出错误,代码不会到达底部)
async
函数的语法是参数列表前面的async
关键字,就像您在原始代码中所做的那样:
const fn = async () => {
const results = [];
for (const url of urls) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(response); // or whatever logic you need with errors
}
results.push(await response.text());
}
// do something with results
};
为了一次有有限数量的请求,创建一个队列系统-当一个请求完成时,递归调用发出另一个请求的函数,类似于:
const results = [];
const queueNext = async () => {
if (!urls.length) return;
const url = urls.shift();
const response = await fetch(url);
if (!response.ok) {
throw new Error(response); // or whatever logic you need with errors
}
results.push(await response.text());
await queueNext();
}
await Promise.all(Array.from({ length: 5 }, queueNext));
// do something with results
不能使用数组方法顺序运行异步操作,因为数组方法都是同步的
实现顺序异步任务的最简单方法是通过循环。否则,您将需要编写一个自定义函数来模拟循环并运行。然后在异步任务结束后运行,这是非常麻烦和不必要的
而且,fetch
已经返回了一个承诺,因此您不必自己创建一个承诺来包含fetch
返回的承诺
下面的代码是一个工作示例,对原始代码进行了一些小的更改(请参见注释)
//例如,伪造URL
常量url=[{url:'abc'},{url:'def',},{url:'ghi'}];
//模仿实际抓取
常量获取=(url)=>新承诺(解析=>{
设置超时(()=>{
决心({
好的,没错,
文本:()=>newpromise(res=>setTimeout(()=>res(url),500))
});
}, 1000);
});
函数getUrl(url、i、cb){
常量获取URL=`https://api.scraperapi.com?api_key=xxx&url=${url.url}`;
返回fetch(fetchUrl)。然后(async res=>{/async/await
就是最好的选择
假设您有一个URL数组作为字符串:
let urls = ["https://example.org/", "https://google.com/", "https://stackoverflow.com/"];
您只需执行以下操作:
for (let u of urls) {
await fetch(u).then(res => {
// Handle response
}).catch(e => {
// Handle error
});
}
在当前的fetch()
解析之前,循环不会迭代,这将序列化内容
数组.map
不起作用的原因如下:
async function doFetch(url) {
return await fetch(url).then(res => {
// Handle response
}).catch(e => {
// Handle error
});
}
相当于:
let mapped;
for (u of urls) {
mapped.push(doFetch(u));
}
这将立即用一堆Promise
s填充mapped
,这不是您想要的。以下是您想要的:
const results = [];
for (const url of urls) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(response); // or whatever logic you need with errors
}
results.push(await response.text());
}
let mapped;
for (u of urls) {
mapped.push(await doFetch(u));
}
但这不是array.map()所说的
确实如此。因此,使用显式的for
循环是必要的。发出请求,并使其与wait一起等待。由于发出请求的承诺是同时解决所有问题。这与for循环中的wait fetch不同要使用wait
,必须使用异步
函数-确保处于async
函数。好的,这可以工作,但是我的vscode编辑器认为它缺少一个异步声明。就像我说的,你需要把它放在一个async
函数中,就像你在原始代码中所做的那样。你试过了吗?它会工作的。是的,它可以工作。它在一个异步函数中,但编辑器认为它缺少一些东西。哦,w嗯。我可以接受这个。你知道我该如何使这个并行运行5次吗?我知道这不是我最初问题的一部分。但每个请求都需要2-3秒的时间。这是针对的吗?我尝试了.map,但它不起作用。我编辑了我的答案,用map()
来解释这个问题。