使用节点向第三方Apis节stream请求

所以我正在build立一个空间地图并把关系转换成一个mongodb。 在这种情况下,我有地区,星座和太阳系。 一个地区可以有多个星座,每个星座可以有多个太阳系。 我有一个允许抓取一些这样的API,但它需要每个项目的API调用。 带来我正在做的问题~6000每天通话。

下面是第三方API标准:

  • 通用速率限制:每秒150个请求
  • 突发尺寸:400
  • 并发连接:20

这里是我的db模型:

地区型号:

var mongoose = require('mongoose'); var Schema = mongoose.Schema; //Schema Definition var regionSchema = new Schema({ _id: Number, name: String, description: String, href: String, constellations: [{ type: Schema.ObjectId, ref: 'Constellation' }]//Reference }); //Expose (export) the model module.exports = mongoose.model('Region', regionSchema); 

星座模式:

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; //Schema Definition var constellationSchema = new Schema({ _id: Number, name: String, href: String, solarSystems: [{ type: Schema.ObjectId, ref: 'SolarSystem' }] }); //Expose (export) the model module.exports = mongoose.model('Constellation', constellationSchema); 

太阳能系统型号:

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; //Schema Definition var solarSystemSchema = new Schema({ _id: Number, name: String, imgUrl: String }); //Expose (export) the model module.exports = mongoose.model('SolarSystem', solarSystemSchema); 

我也试图把它们保存在适当的顺序,所以引用填充关系。

这是我的代码:

 function getAllRegions(req, res){ getAllRegionsHrefs().then(function (hrefs){ var newRegions = []; for(var href in hrefs){ var options = { uri: hrefs[href], json: true }; RequestPromise(options).then(function (responseItem){ var constellationObjects = []; for(var item in responseItem.constellations){ var newConstellation = constellationModel({ _id: responseItem.constellations[item].id, href: 'https://getspaceInfoHere.com/constellations/'+responseItem.constellations[item].id+'/' }); newConstellation.save(); constellationObjects.push(newConstellation); } var newRegion = regionModel({ _id: responseItem.id, name: responseItem.name, description: responseItem.description, href: 'https://getspaceInfoHere.com/regions/'+responseItem.id+'/', constellations: constellationObjects }); newRegion.save(); newRegions.push(newRegion); console.log(newRegion); }); } }); } function getAllRegionsHrefs(){ var options = { uri: universeInfoEndpoint, json: true }; return RequestPromise(options).then(function (responseItems){ var regionHrefs = []; for(var item in responseItems.items){ regionHrefs.push(responseItems.items[item].href); } return regionHrefs; }); } 

现在我甚至不试图得到详细的星座信息,它提供了系统信息(然后提供一个href来获得详细的系统信息),我正在运行到我的最大。 什么是最好的方法来节制这个,所以我可以留在参数?

UPDATE

 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); }); }); } function getSystem(systems){ for(var updateSystem in systems){ var options = { uri: systems[updateSystem].href, json: true }; RequestPromise(options).then(function (responseItem){ //Grab the system in the db and update it with its info systemModel.findOne({ _id: systems[updateSystem]._id }, function (err, doc){ doc.name = responseItem.name; doc.save(); }); }); } } function getConstellationInfo(constellation) { var options = { uri: constellation.href, json: true }; return RequestPromise(options).then(function (responseItem){ var arrayOfSystems = []; for(var system in responseItem.systems){ var newSystem = new systemModel({ _id: responseItem.systems[system].id, href: responseItem.systems[system].href }); newSystem.save(); arrayOfSystems.push(newSystem); } //find the constellation and update it with its info constellationModel.findOne({ _id: constellation._id }, function (err, doc){ doc.name = responseItem.name; doc.solarSystems = arrayOfSystems; doc.save(); }); return arrayOfSystems; }); } function getRegion(href) { var options = { uri: href, json: true }; return RequestPromise(options).then(function (responseItem){ var constellationObjects = []; for(var item in responseItem.constellations){ var newConstellation = constellationModel({ _id: responseItem.constellations[item].id, href: eveConstellationCrestEndpoint + responseItem.constellations[item].id+'/' }); newConstellation.save(); constellationObjects.push(newConstellation); } var newRegion = regionModel({ _id: responseItem.id, name: responseItem.name, description: responseItem.description, href: universeEndpoint + responseItem.id+'/', constellations: constellationObjects }); newRegion.save(); return newRegion; }); } function getAllRegionsHrefs(){ var options = { uri: universeEndpoint, json: true }; return RequestPromise(options).then(function (responseItems){ var regionHrefs = []; for(var item in responseItems.items){ regionHrefs.push(responseItems.items[item].href); } return regionHrefs; }); } 

现在,这是工作在整个链(获取区域,星座和系统信息),但超时正在工作,并开始拒绝在系统级别的连接。 有什么build议?

你可以通过将你的hrefs分成20个集合并在每个chunk之后设置一个延迟来达到这个目的,你可能需要使用这些参数:

使用lodash的_.chunk和Bluebird的Promise.delayPromise.map

 function getAllRegions(req, res){ getAllRegionsHrefs().then(function (hrefs){ var chunks = _.chunk(hrefs, 20); return Promise.map(chunks, function(chunk) { // tune the delay to what you need it to be // it will wait the delay (in ms) before starting the next chunk of requests return Promise.map(chunk, getRegion).delay(150000); }); }); } function getRegion(href) { var options = { uri: hrefs[href], json: true }; return RequestPromise(options).then(function (responseItem){ var constellationObjects = []; for(var item in responseItem.constellations){ var newConstellation = constellationModel({ _id: responseItem.constellations[item].id, href: 'https://getspaceInfoHere.com/constellations/'+responseItem.constellations[item].id+'/' }); newConstellation.save(); constellationObjects.push(newConstellation); } var newRegion = regionModel({ _id: responseItem.id, name: responseItem.name, description: responseItem.description, href: 'https://getspaceInfoHere.com/regions/'+responseItem.id+'/', constellations: constellationObjects }); newRegion.save(); console.log(newRegion); return newRegion; }); }