Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/43.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 延迟承诺。所有顺序_Javascript_Node.js - Fatal编程技术网

Javascript 延迟承诺。所有顺序

Javascript 延迟承诺。所有顺序,javascript,node.js,Javascript,Node.js,我正在从外部API获取数据,在某些端点上出现以下错误: reason: getaddrinfo EAI_AGAIN [the url]:443 我只能假设API的所有者有某种速率限制,因为所有的抓取都是一次性完成的,所以一些URL会被阻止 所以我试图在每次抓取之间设置一个延迟,但没有运气。以下是我的尝试: class someClass { ... dealyedFetch(url) { return new Promise ((resolve, reject) => {

我正在从外部API获取数据,在某些端点上出现以下错误:

reason: getaddrinfo EAI_AGAIN [the url]:443
我只能假设API的所有者有某种速率限制,因为所有的抓取都是一次性完成的,所以一些URL会被阻止

所以我试图在每次抓取之间设置一个延迟,但没有运气。以下是我的尝试:

class someClass {
  ...
  dealyedFetch(url) {
    return new Promise ((resolve, reject) => {
      setTimeout(() => {
        fetch(url, (err, res) => { 
          if (err) return reject(err)
          return resolve(res)
        })
      }, 5000)    
    })
  }

  fetchUrls() {
    return Promise.all(
      this.urlList.map(url => {
        return this.dealyedFetch(url)
        .then(/* macht krieg */)
        .catch(err => ({err, url}))
      })
    )
  }    
}

上述方法不起作用,它似乎一次触发了所有抓取操作。请告诉我。

对于您的
urlist
,您同时做出了一系列承诺。每一个承诺都会等待5秒,然后它们都会同时执行(5秒后)

有关以串行方式运行承诺的规范SO post,请参见以下内容:

从该职位上解除:

function runSerial(tasks) {
  var result = Promise.resolve();
  tasks.forEach(task => {
    result = result.then(() => task());
  });
  return result;
}

然后你会用runSerial替换你的promise.all来消耗它。您可以通过一次释放5个url来进一步自定义逻辑,然后以串行方式运行批处理,但这应该可以让您开始了。

您一次延迟了所有批处理,因此它们都等待5000毫秒,然后一起触发

如果你想把它们串起来,你需要让它们的延迟时间逐渐延长。您可以使用
映射中的索引将延迟(例如500毫秒)乘以:

delayedFetch(url, delay) {                   // ***
  return new Promise ((resolve, reject) => {
    setTimeout(() => {
      fetch(url, (err, res) => { 
        if (err) return reject(err)
        return resolve(res)
      })
    }, delay)                                // ***
  })
}
fetchUrls() {
  return Promise.all(
    this.urlList.map((url, i) => {           // ***
      return this.delayedFetch(url, i * 500) // ***
      .then(/* macht krieg */)
      .catch(err => ({err, url}))
    })
  )
}    
第一个请求根本不会延迟,第二个请求是1*500=500ms,第三个请求是2*500=1000ms,以此类推


旁注:在上文中,我修复了名称
delayedFetch
中的一个拼写错误(问题中
dealyedFetch
a
l
被颠倒)


边注2:上面提到了你实际提出的问题,但是你可以考虑一次做一个,在这种情况下告诉你如何做到这一点。或者对未完成的部分设置并发限制,在这种情况下会有所帮助。仅仅一个固定的延迟可能不是最好的解决方案。

可能会将延迟传递给
delayedFetch
,并基于数组中的索引,如
this.urlist.map((url,index)=>…delayedFetch(url,index*1000)…
以不同的方式偏移它们中的每一个。
承诺。all
不能使任何事情连续,它只是等待。您正在触发所有的
delayedFetch
调用(它们都使用相同的超时!)在
map
呼叫的同一瞬间。如果那里的答案回答了这个问题,正确的做法是投票以重复的方式结束(可能还带有注释),而不是发布一个回答说“去看看这个其他答案”(无论是否引用部分答案).@T.J.Crowder在我看来,作为一个复制品结束并不能解决问题的根本问题。我知道,复制品对我如何做X很有帮助,而不是我在做Y,但它不起作用,所以有一个明确的政策,什么是复制品,什么不是复制品:如果答案回答了问题,那么它就是复制品。(现在,在我看来,这个问题在这里不会是一个双重问题,因为它回答了一个不同的问题——尽管它可能指向一个不同的方法来解决这个OP的根本问题。)您认为在这里使用异步函数更有意义吗?@S.Schenk:
async
函数只是返回承诺的函数的语法糖。不过,它确实是非常有用的糖,如果您可以使用它,那就太好了。(如果您使用的是任何最新版本的节点,您也可以这样做。)例如,如果您想一次只执行一个请求(例如,按顺序)使用
async
/
await
它是
const results=[];for(this.urlsist的const url){results.push(await fetch(url));}
函数中的
async
函数。一次具有多个并发限制会更复杂。