Node.js(ES6) - 使用Promise.all

时间:2015-12-15 00:40:28

标签: node.js request queue promise es6-promise

我正在尝试创建一个处理并行HTTP请求的队列。

为每个HTTP请求生成一个请求对象,例如

{
    method: 'POST',
    uri: 'http://posttestserver.com/post.php',
    body: {
        some: 'foo'
    },
    json: true
}

我传入了这些对象的数组,并希望将它们添加到队列中,然后执行实际的请求。

问题:Promise.all语句在返回之前等待所有请求完成。

问题:我希望将所有任务添加到队列中,并在每次请求完成后返回,而不是等待所有任务。任何人都可以建议如何分离逻辑以使请求从队列中添加任务?

注意:promise-queue和request-promise都返回promises。

以下是我所拥有的:

"use strict";

const Queue = require("promise-queue");
const rp = require('request-promise');

const maxConcurrent = 10;
const maxQueue = Infinity;
const queue = new Queue(maxConcurrent, maxQueue);

var options = [
    {
        method: 'POST',
        uri: 'http://posttestserver.com/post.php',
        body: {
            some: 'foo'
        },
        json: true
    },{
        method: 'POST',
        uri: 'http://posttestserver.com/post.php',
        body: {
            some: 'bar'
        },
        json: true
    }
];

Promise.all(options.map(function(task) {
        return queue.add(function() {
            return rp(task);
        })
    }))
    .then(function(response) {
        log(response);
    })
    .catch(function(err) {
        log(err);
    });


function log(data) {
    console.log(JSON.stringify(data, undefined, 4));
}

1 个答案:

答案 0 :(得分:2)

我建议在forEach循环中调用promise链,如下所示:

var queueTask = function(task) {
  // returns a promise
  return queue.add(function() { return rp(task); });
};

var logResponse = function(response) {
  console.log(response);
};

var catchErrors = function(err) {
  console.log(err);
};

options.forEach(opt => {
  queueTask()
    .then(logResponse)
    .catch(catchErrors);
})

<强>更新

在评论中提到,上面的代码片段并没有让您知道上一个任务何时完成。这不是原始问题的要求,但由于一些评论说它可能有用,这里有一种方法可以使用promises来实现:

var runTasks = new Promise(function(resolve, reject) {

  var queueTask = function(task) {
    // returns a promise
    return queue.add(function() { return rp(task); });
  };

  var logResponse = function(response) {
    console.log(response);
  };

  var catchErrors = function(err) {
    console.log(err);
  };

  options.forEach((opt, i, arr) => {
    
    queueTask()
      .then(logResponse)
      .catch(catchErrors);
    
    if (i === arr.length-1) { resolve(); }
    
  });
  
});

var functionToRunWhenLastTaskCompletes = function() {
  console.log('All tasks are complete.');
};

// runTasks is a promise here, not a function
// so you don't need to call it like a function
runTasks
  .then(functionToRunWhenLastTaskCompletes)