Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在串行中列出一长串http调用?_Javascript_Node.js_Ecmascript 5_Ecmascript 2016 - Fatal编程技术网

Javascript 如何在串行中列出一长串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

我试图一次只进行一次http调用,但当我记录来自
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()
来解释这个问题。