Node.js 为什么这个应用程序会停滞?
我有下面的应用程序,它暂停(代码如下)。我不知道为什么。我怀疑我可能用错了瓶颈模块 免责声明:我正在尝试学习编程,并在使用这个项目时自学NodeJS。请帮忙 简介 该应用程序的要点是通过请求一个网页并以jQuery风格对其进行解析来获取数据库中文档中缺失的数据。然后将返回的数据保存到文档中的新键。该数据库由约92000份文件组成。应用程序使用、和模块。我在OSX上运行应用程序 问题 如果我对请求的数量设置了限制,例如Node.js 为什么这个应用程序会停滞?,node.js,mongodb,request,cheerio,Node.js,Mongodb,Request,Cheerio,我有下面的应用程序,它暂停(代码如下)。我不知道为什么。我怀疑我可能用错了瓶颈模块 免责声明:我正在尝试学习编程,并在使用这个项目时自学NodeJS。请帮忙 简介 该应用程序的要点是通过请求一个网页并以jQuery风格对其进行解析来获取数据库中文档中缺失的数据。然后将返回的数据保存到文档中的新键。该数据库由约92000份文件组成。应用程序使用、和模块。我在OSX上运行应用程序 问题 如果我对请求的数量设置了限制,例如 var limiter = new bottleneck(5, 0); 应用
var limiter = new bottleneck(5, 0);
应用程序在第一批之后暂停(本例中为5)。但是为什么呢?我怀疑瓶颈和它期望我的程序如何工作可能有问题。可能与回调有关
如果我没有设置限制,应用程序就可以正常工作。它获取网页并写入数据库。但是,由于资源过载而导致的错误很多,因此速度较慢。这就是我告诉瓶颈不要限制的方式:
var limiter = new bottleneck(0, 0);
以下是我遇到的错误类型:
{ [Error: getaddrinfo ENOTFOUND www.vestnikverejnychzakazek.cz www.vestnikverejnychzakazek.cz:443]
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'www.vestnikverejnychzakazek.cz',
host: 'www.vestnikverejnychzakazek.cz',
port: 443 }
{ [Error: connect EMFILE 65.52.146.11:443 - Local (undefined:undefined)]
code: 'EMFILE',
errno: 'EMFILE',
syscall: 'connect',
address: '65.52.146.11',
port: 443 }
应用程序代码
'use strict';
var express = require('express');
var router = express.Router();
var assert = require('assert');
var mongo = require('mongoskin');
var path = require('path');
var ObjectID = require('mongodb').ObjectID;
var db = mongo.db("mongodb://localhost:27017/zak", {
native_parser: true
});
var database = db.collection("zakazky");
var cheerio = require("cheerio");
var request = require("request");
var fs = require("fs");
var toJs = (path.join(__dirname, '../public/javascripts', 'jquery.min.js'));
var jquery = fs.readFileSync(toJs).toString();
var bottleneck = require("bottleneck");
var limiter = new bottleneck(5, 0);
/* GET home page. */
router.get('/', function(req, res) {
var cursor = database.find();
cursor.each(function(err, data) {
assert.equal(err, null);
if (data != null) {
var vvz = "vestnikverejnychzakazek";
var praha = "zakazky.praha.eu";
var id = data["_id"];
var zdroj = data["zdroj"];
if (zdroj.indexOf(vvz) > -1) {
if ((data["cpv"] == null) || (data["predpokladana_hodnota"] == null)) {
limiter.submit(getCPV, id, zdroj, null);
// getCPV(id, zdroj);
} else {
// console.log("we're good");
return
}
} else if (zdroj.indexOf(praha) > -1) {
// console.log("pha");
}
} else {
// callback();
}
});
var getCPV = function(id, zdroj, callback) {
console.log("CPV started");
var zdroj = zdroj.replace("http://", "https://");
console.log("zdroj: " + zdroj);
var cpv = [];
var retryWrapper = function(retries) {
var retries; // I added this
if (retries === 3) {
return;
} else if (retries === undefined) {
retries = 0;
} else if (retries > 0) {
console.log("trying again");
}
request(zdroj, function(err, resp, data) {
if (err) {
console.log(err);
return retryWrapper(retries + 1);
}
var $ = cheerio.load(data);
var predpokladnaHodnota = $("[id*='Hodnota1_']").first().attr("value");
$("[id*='HlavniSlovnik']").each(function() {
cpv.push(this.attribs.value);
});
// let's check what we've got is actual data
if (cpv.length === 0) {
return
} else {
// send it off
writeCPV(id, "cpv", cpv)
}
if (predpokladnaHodnota == undefined || predpokladnaHodnota == null) {
return
} else {
// send it off
writeCPV(id, "predpokladana_hodnota", predpokladnaHodnota)
}
callback();
});
}; // end of retryWrapper
retryWrapper();
};
var writeCPV = function(id, key, value) {
id = ObjectID(id);
(function() {
console.log("starting DB write 1");
database.update({
"_id": id
}, {
$set: {
[key]: value
}
}, function(err, results) {
if (err) {
console.log("error in Mongo DB: \n------------------------\n" + err);
}
console.log("Mongo success!:\n ----------------------\n" + results);
// callback();
});
})();
};
// send the browser we're done
res.sendStatus(200);
});
// ---------------------
module.exports = router;
以下是数据库中的示例文档,包括获取的密钥:
{
"_id": ObjectId("568d91396912101c1007ab4e"),
"cena": 1636363,
"cena_celkem": 1500000,
"cena_dopocitano": false,
"created": "2015-04-07T13:45:10.420739",
"datum_zadani": "2015-02-16",
"dodavatel": "/api/v1/dodavatel/381836/",
"druh_rizeni": "/api/v1/druh_rizeni/1116/",
"id": 1312587,
"modified": "2015-04-18T14:22:10.765733",
"nazev": "Pohostinství",
"pocet_nabidek": 2,
"podporeno_eu": true,
"popis": "Kurzy v oblasti pohostinství (formou profesní kvalifikace)",
"ramcova_smlouva": true,
"resource_uri": "/api/v1/zakazka/1312587/",
"skupina": "490648-ISVZUS_2011",
"typ_zakazky": "/api/v1/typ_zakazky/193/",
"zadavatel": "/api/v1/zadavatel/131528/",
"zdroj": "http://www.vestnikverejnychzakazek.cz/en/Form/Display/568547",
"zdroj_nazev": "isvzus.cz",
"cpv": ["80000000-4", "80400000-8", "", "", ""],
"predpokladana_hodnota": "1 500 000,00"
}
正在请求的示例URL:
http://www.vestnikverejnychzakazek.cz/en/Form/Display/568547
这已经在这里有一段时间了,但如果其他人偶然发现这一点,希望这将有助于某人
限制器正在调用getCPV,并且它确实在序列的末尾调用回调,但是,retryWrapper中有一些条件语句允许提前返回,因此从不调用回调。限制器将堆积起来,直到触发为止,因此始终确保在所有情况下都会触发回调。这已经在这里出现了一段时间,但如果其他人意外发现,希望这将有助于他人 限制器正在调用getCPV,并且它确实在序列的末尾调用回调,但是,retryWrapper中有一些条件语句允许提前返回,因此从不调用回调。限制器将堆积起来,直到触发为止,因此始终确保在所有场景中都会触发回调