延迟承诺:.delay()似乎不起作用

时间:2016-07-28 02:15:35

标签: node.js asynchronous promise bluebird

这是来自Throttling requests to 3rd part Apis with Node的扩展问题。如果您想查看子功能以及我想要做的事情的一些背景故事,您可以在该帖子中看到我的完整代码。

我需要做的是将api请求延迟到api。我每秒钟达到服务器最大值。我试图使用Promise.delay但它似乎没有任何东西。这就是我如何使用它。

function getAllRegions(req, res){
    getAllRegionsHrefs().then(function (hrefs){
        var chunks = _.chunk(hrefs, 25);
        return Promise.map(chunks, function(chunk) {
            return Promise.map(chunk, getRegion).then(function (getRegionResults){
                for(var item in getRegionResults) {
                    Promise.map(getRegionResults[item].constellations, getConstellationInfo).then(function (constellationInfo) {
                        var chunks = _.chunk(constellationInfo, 150);
                        return Promise.map(chunks, function (chunk) {
                            return Promise.map(chunk, getSystem).delay(20000);
                        })
                    }).delay(20000);
                }
            }).delay(200000);
        });
    });
}

现在这将只产生大约9k api请求,并且它构建了一个基于区域,星座和系统的宇宙。是否有更好的方法来限制嵌套请求?在每个嵌套中,调用次数呈指数上升。

更新

似乎还不想等待。我是否再次陷入困境?我在那里添加了另外一个流程所需的功能。此外,分块似乎包裹了一个双阵列,所以我把它拿出来了。

function getAllRegions(req, res) {
    getAllRegionsHrefs().then(function (hrefs) {
        return Promise.mapSeries(hrefs, function (href) {
            getRegion(href).then(function (regions) {
               return Promise.mapSeries(regions.constellations, function (constellation) {
                    getConstellationInfo(constellation).then(function (constellationInfo) {
                        return Promise.map(constellationInfo, getSystem).delay(15000);
                    });
                });
            });
        });
    });
}

错误(每个请求):

 Unhandled rejection RequestError: Error: connect ETIMEDOUT

1 个答案:

答案 0 :(得分:1)

Promise.map并行启动所有请求,因此您的代码运行如下:

  • 请求 - >延迟
  • 请求 - >延迟
  • 请求 - >延迟
  • ....

但是所期望的行为应该是连续的:

  • 请求 - >延迟 - >请求 - >延迟 - >请求 - >延迟......

每个请求块应该等待前一个块的延迟。

你可以通过链接承诺来实现这一目标:

startRequests(chunks[0])
.then(function() {
  return startRequests(chunks[1])
}).then(function() {
  return startRequests(chunks[2])
}) // ...

或使用mapSeries

function getAllRegions(req, res){
  getAllRegionsHrefs().then(function(hrefs) {
    return Promise.mapSeries(hrefs, function(href) {
      getRegion(href).then(function(region) {
        var chunks = _.chunk(region.constellations, 150);
        return Promise.mapSeries(chunks, function (chunk) {
          return Promise.map(chunk, getSystem).delay(10000);
        });
      });
    });
  });
}

只有最里面的请求被分块,其他请求一个接一个地启动。

编辑:正如Bergi所说,mapSeries(以及其他承诺实用程序)需要返回结果承诺。第一个承诺也可以返回以处理错误或链接更多的承诺。

function getAllRegions(req, res){
  return getAllRegionsHrefs().then(function(hrefs) {

//...

getAllRegions().then(systems => {
  //next step
}).catch(err => {
  //handle errors
})