对多个节点请求使用 Promise

cus*_*ice 2 node.js promise express

有了request库,有没有办法使用 Promise 来简化这个回调?

  var context = {};

  request.get({
    url: someURL,
  }, function(err, response, body) {

    context.one = JSON.parse(body);

    request.get({
      url: anotherURL,
    }, function(err, response, body) {
      context.two = JSON.parse(body);

      // render page
      res.render('pages/myPage');
    });
  });
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 5

这是使用 Bluebird Promise 库的解决方案。这会序列化两个请求并将结果累积到对象中context,并将错误处理全部汇总到一处:

var Promise = require("bluebird");
var request = Promise.promisifyAll(require("request"), {multiArgs: true});

var context = {};
request.getAsync(someURL).spread(function(response, body) {
    context.one = JSON.parse(body);
    return request.getAsync(anotherURL);
}).spread(response, body)
    context.two = JSON.parse(body);
    // render page
    res.render('pages/myPage');
}).catch(function(err) {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

而且,如果您有多个 URL,您可以使用 Bluebirds 的一些其他功能,例如Promise.map()迭代 URL 数组:

var Promise = require("bluebird");
var request = Promise.promisifyAll(require("request"), {multiArgs: true});

var urlList = ["url1", "url2", "url3"];
Promise.map(urlList, function(url) {
    return request.getAsync(url).spread(function(response,body) {
        return [JSON.parse(body),url];
    });
}).then(function(results) {
     // results is an array of all the parsed bodies in order
}).catch(function(err) {
     // handle error here
});
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个辅助函数来为您执行此操作:

// pass an array of URLs
function getBodies(array) {
    return Promise.map(urlList, function(url) {
        return request.getAsync(url).spread(function(response.body) {
            return JSON.parse(body);
        });
    });
});

// sample usage of helper function
getBodies(["url1", "url2", "url3"]).then(function(results) {
    // process results array here
}).catch(function(err) {
    // process error here
});
Run Code Online (Sandbox Code Playgroud)