使用node.js async和require获取多个url

Using node.js async and require to fetch multiple urls

本文关键字:获取 url require node js async 使用      更新时间:2023-09-26

你好——我对这个主题进行了很多查询,但找不到一个适合我情况的好例子。

目标:使用request和async调用多个url(这些url是不同的,有些是xml,有些是json),具有扩展链接数量的能力,最终结果是将数据传递给视图进行解析。

代码:

var express = require('express');
var router = express.Router();
var request = require('request');
var parseString = require('xml2js').parseString;
var async = require('async');
var bis;
var url_bis = {
  url: 'https://www.bis.org/list/cbspeeches/index.rss',
  headers: {
    'User-Agent': 'request'
  }
};
function callback_bis(error, response, body) {
  if (!error && response.statusCode == 200) {
    bis = "";
    parseString(body, function (err, result) {
        bis = result;
        bis = bis["rdf:RDF"]["item"];
    });
  }
}
var doj;
var url_doj = {
  url: 'http://www.justice.gov/feeds/opa/justice-news.xml',
  headers: {
    'User-Agent': 'request'
  }
};
function callback_doj (error, response, body) {
  if (!error && response.statusCode == 200) {
    doj = "";
    parseString(body, function (err, result) {
        _doj = result;
        doj = _doj.rss.channel[0].item;
    });
  }
}   
function feed_doj() {
    request(url_doj, callback_doj);
}
function feed_bis() {
    request(url_bis, callback_bis);
}
router.get('/', function(req, res, next) {
async.parallel({
    bis: feed_bis,
    doj: feed_doj
}, function(err, results) {
    console.log(results)
    // how to get the bis/doj response here in results?
});
});
module.exports = router;

使用承诺和Promise.all()函数这是非常容易的:

var request = require('request-promise');
var calls = [
  request({ url: 'http://...', headers: { ... } }),
  request({ url: 'http://...', headers: { ... } }),
  // ...as many more as you want...
];
Promise.all(calls).then(function(results) {
  // do something with results[0]
  // do something with results[1]
});

Promise API在新版本的JS中是原生的,并且可以很容易地在旧的JS引擎中填充,因此它减少了对async等辅助库的需求。

本例并行运行所有请求。Promise.all()等待它们全部完成,然后为您提供与原始请求匹配的结果数组。还请注意request-promise模块的使用,它只是在request模块的基础上,但返回一个承诺,而不是接受一个回调。

async需要知道你什么时候完成了每个任务。为了实现这一点,调用任务时使用回调函数作为参数。您的任务函数feed_dojfeed_bis应该调用回调函数。这也是从任务中获得输出的标准方式——不要使用全局函数,它被广泛认为是不好的形式。这样做:

function feed_bis(callback) {
  function callback_bis(error, response, body) {
    if (!error && response.statusCode == 200) {
        parseString(body, function (err, result) {
        var bis = result["rdf:RDF"]["item"];
        callback(null, bis);
      });
    }
  }
  request(url_bis, callback_bis);
}
// And same again for doj

一旦bis和doj的callback函数被调用,主回调函数将带参数(err, result)被调用;err将是null,因为您没有做任何事情来处理错误情况,result将是一个具有属性名为bisdoj的对象。

您可以使用async模块中包含的并行方法来完成此操作,您只需将所有请求推送到数组中,然后实现此:https://github.com/caolan/async/blob/master/README.md#parallel它旨在在所有进程结束时执行最终回调。