在使用AngularFire测试Firebase时,我对它的速度感到惊讶。经过进一步的测试,我发现Firebase不是很慢,但是AngularFire很慢(在Firefox v26.0中非常慢)。
我的用例是我需要访问给定父级的多个孩子的地方。孩子的总数可能会达到数千人,因此不能同时取出所有孩子。此外,他们需要从祖父母那里访问,因此优先查询并不总是一种选择。
在这个使用AngularFire(慢)的示例中,我有什么问题吗? http://plnkr.co/edit/eML3HF3RtchIU26EGVaw?p=preview
使用AngularFire访问儿童的要点:
function getChild(childID) {
recordCount++;
myC.children[childID] = $firebase(new Firebase(childrenUrl + childID));
myC.children[childID].$on('loaded', function () {
returnCount++;
checkReturnCount();
});
}
function checkReturnCount() {
if (recordCount != 0 && recordCount == returnCount) {
var diff = (new Date).getTime() - start;
myC.log.push("Loaded " + parent.FirstName + "'s children in " + diff + "ms.");
$scope.$apply();
}
}
为了进行比较,请参阅此示例,该示例未使用任何Angular插件(快速): http://plnkr.co/edit/GA17FEnHu7p8wAiDXA5b?p=preview
访问没有AngularFire的孩子的要点
function getChild(childID) {
recordCount++;
var tempRef = new Firebase(childrenUrl + childID);
tempRef.on('value', function (data) {
myC.children[childID] = data.val();
returnCount++;
checkReturnCount();
});
}
function checkReturnCount() {
if (recordCount != 0 && recordCount == returnCount) {
var diff = (new Date).getTime() - start;
myC.log.push("Loaded " + parent.FirstName + "'s children in " + diff + "ms.");
$scope.$apply();
}
}
答案 0 :(得分:1)
好的,我可能找到了解决方案。显然,Firefox曾经将随机时间添加到它的setTimeouts中,但它不再存在(参见https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)。但是,Firefox(以及其他浏览器)显然仍然具有最小超时延迟(在FF中显然是4ms)。
此页面提出了一个解决方案:http://dbaron.org/log/20100309-faster-timeouts
以下是该博客文章中的setZeroTimeout方法:
// Only add setZeroTimeout to the window object, and hide everything
// else in a closure.
(function() {
var timeouts = [];
var messageName = "zero-timeout-message";
// Like setTimeout, but only takes a function argument. There's
// no time argument (always zero) and no arguments (you have to
// use a closure).
function setZeroTimeout(fn) {
timeouts.push(fn);
window.postMessage(messageName, "*");
}
function handleMessage(event) {
if (event.source == window && event.data == messageName) {
event.stopPropagation();
if (timeouts.length > 0) {
var fn = timeouts.shift();
fn();
}
}
}
window.addEventListener("message", handleMessage, true);
// Add the one thing we want added to the window object.
window.setZeroTimeout = setZeroTimeout;
})();
当我使用这个setZeroTimeout方法时,使用AngularFire似乎并不比使用基本API慢得多。
为了比较,我使用它而不是$ timeout服务创建了一个新的Plnkr。
这可以包含在AngularFire中吗?或者我现在应该修改我的版本吗?
答案 1 :(得分:1)
好的,我想我已经对上面开始提出的解决方案进行了进一步的改进,这也会根据需要触发角度摘要周期:
我在AngularFire函数中覆盖了_timeout函数,如下所示:
this._timeout = function (fn) {
fn();
throttledApply();
};
throttledApply在$ firebase工厂中定义为:
var throttledApply = _.throttle(apply, 100);
function apply() {
$rootScope.$apply();
}
然后传递给AngularFire函数而不是$ timeout服务。它利用下划线的油门功能立即调用$ apply,然后每100ms调用一次。就我的目的而言,这已足够。它可以很容易地减少到更像50毫秒或25毫秒的东西。
我没有看到这些修改的影响吗?