当然,我有一个通过ExpressJS在NodeJS上发布的网络应用程序。它使用CouchDB作为它的数据源。我实施了长轮询,以确保所有用户之间的应用始终保持同步。为此,我使用以下逻辑:
简单。然而,正在发生的事情是,当我刷新浏览器时,它会冻结每五次刷新。咦?非常奇怪。但我可以一遍又一遍地重现它,即使在我的测试环境中也是如此。每隔五次刷新就会冻结Node并导致应用程序冻结。重新启动节点可以解决问题。
经过大量的头发拉动我 THOUGHT 我通过更改它来解决它:
app.get('/_changes/:since*', security, routes.changes);
对此:
app.get('/_changes/:since*', security, function () { routes.changes });
然而,在进一步测试之后,这只是无法运行routes.changes。所以没有实际解决方案任何想法为什么长期轮询来自Node的CouchDb会做出如此奇怪的事情?在第五次刷新时,我可以在我的路由代码的第一行的节点中有一个断点,它永远不会被击中。但是,在浏览器中我可以打破对节点进行长轮询的请求,它似乎会消失。这就像Node因某种原因不接受连接......
我是否应该以不同的方式接近从Node到CouchDB的长轮询?我正在使用feed = longpoll,我应该做feed =连续吗?如果我将couchdb中的changes_timeout调低到5秒,它就不会解决问题,但它确实更容易应对,因为冻结仅持续5秒钟。所以这似乎表明节点无法处理几个未完成的请求。也许我会尝试连续喂食,看看会发生什么。
self.getChanges = function(since){
浏览器:
$.ajax({
url: "/_changes/" + since,
type: "GET", dataType: "json", cache: false,
success: function (data) {
try {
self.processChanges(data.results);
self.lastSeq(data.last_seq);
self.getChanges(self.lastSeq());
self.longPollErrorCount(0);
} catch (e) {
self.longPollErrorCount(self.longPollErrorCount() + 1);
if (self.longPollErrorCount() < 10) {
setTimeout(function () {
self.getChanges(self.lastSeq());
}, 3000);
} else {
alert("You have lost contact with the server. Please refresh your browser.");
}
}
},
error: function (data) {
self.longPollErrorCount(self.longPollErrorCount() + 1);
if (self.longPollErrorCount() < 10) {
setTimeout(function () {
self.getChanges(self.lastSeq());
}, 3000);
} else {
alert("You have lost contact with the server. Please refresh your browser.");
}
}
});
}
节点:
路由:
exports.changes = function (req, res) {
var args = {};
args.since = req.params.since;
db.changes(args, function (err, body, headers) {
if (err) {
console.log("Error retrieving changes feed: "+err);
res.send(err.status_code);
} else {
//send my response... code removed here
}
})
}
数据库长轮询调用:
self.changes = function (args, callback) {
console.log("changes");
if (args.since == 0) {
request(self.url + '/work_orders/_changes?descending=true&limit=1', function (err, res, headers) {
var body = JSON.parse(res.body);
var since = body.last_seq;
console.log("Since change: "+since);
self.longPoll(since, callback);
});
} else {
self.longPoll(args.since, callback);
}
}
self.longPoll = function (since, callback) {
console.log("about to request with: "+since);
request(self.url + '/work_orders/_changes?feed=continuous&include_docs=true&since=' + since,
function (err, res, headers) {
console.log("finished request.")
if (err) { console.log("Error starting long poll: "+err.reason); return; } //if err send it back
callback(err, res.body);
});
}
答案 0 :(得分:0)
Socket.io将自动回退到长轮询,并且没有像您所拥有的那样的问题。所以就这样使用它。另外,对于CouchDB更改,请使用此https://github.com/iriscouch/follow或者像其他人建议的那样https://npmjs.org/package/changes。
当我们拥有已经满足你需要的流行模块时,重新发明的东西是非常糟糕的做法。目前https://npmjs.org/上有超过52,000个节点模块。人们在复制和粘贴代码方面做了大量工作。在我看来,重塑基本的东西比这更糟糕。
我知道有很多模块很难知道所有这些模块,所以我并不是说你永远无法解决与其他人相同的问题。但首先看看npmjs.org以及http://node-modules.com/之类的网站,它们可能会提供更好的搜索结果。