对于我的角度应用程序,我正在尝试跟踪已处理的承诺数量以及仍需要处理的数量。
我的代码使用包装器方法修饰$ q,无论何时启动操作并且只要一个操作完成,更新一个简单的计数器似乎很简单:
angular.module('DuckieTV',[])
.config(function($provide) {
var count = window.promiseStats = {
open: 0,
done: 0
};
$provide.decorator('$q', function($delegate) {
function decorate(p) {
p._then = p.then;
p.then = function(thenFn, errFn, notifyFn) {
count.open++;
return p._then(function() {
count.done++;
if(thenFn) return thenFn.apply(this,arguments)
}, function() {
count.done++;
if(errFn) return errFn.apply(this,arguments)
}, notifyFn);
};
p._finally = p.finally;
p.finally = function(callback) {
count.done++;
p._finally(callback)
}
p._catch = p.catch;
p.catch = function(callback) {
count.done++;
p._catch(callback)
}
return p;
}
var d = $delegate.defer;
$delegate.defer = function() {
var deferred = d();
decorate(deferred.promise);
return deferred;
};
return $delegate;
});
})
当我注意到已启动/已完成的承诺之间的差异时,乐趣就开始了。在执行大量延期操作几分钟后,它可以成为一个>总体比例为15%。
控制台输出示例:
promiseStats
Object {open: 99, done: 95}
Math.floor(promiseStats.done / promiseStats.open * 100);
94
经过一些工作(导入操作)
promiseStats;
Object {open: 185, done: 172}
Math.floor(promiseStats.done / promiseStats.open * 100);
92
我的实际问题:任何人都可以告诉我,如果我错过了这个实现的东西吗?
据我所知,我没有错过任选的实现和我通过的所有承诺。然后正确编码
答案 0 :(得分:2)
任何人都可以告诉我,如果我错过了这个实现的内容吗?
我可以看到您的实施有两个问题:
catch
和invoke
方法只增加done
次,而不是open
次。由于您没有看到这一点,我猜您还没有在您的代码中使用过。通过向每个onfail
调用引入.then()
处理程序,您隐式捕获所有错误并严重hurt control flow。您可以通过将以下行附加到处理程序代码来解决此问题:
…
else throw arguments[0];
我注意到已启动/已完成的承诺之间的差异
我不认为这是由你的计数器实施引起的。相反,你真的在你的代码中有一些永远未决的承诺;即从未解决的延期。例如,这可能是由使用deferred antipattern的代码中的错误引起的。
我的代码使用包装器方法装饰
$q
,无论何时启动操作并且只要一个操作完成,它就会更新一个简单的计数器,这看起来很简单:
事实上,只要连接侦听器,它就会更新计数器,即调用then
/ catch
/ finally
方法。我建议一个更简单的实现,依靠创建,甚至不需要覆盖这些方法:
$provide.decorator('$q', function($delegate) {
var defer = $delegate.defer;
$delegate.defer = function() {
var deferred = defer();
count.open++;
deferred.promise.finally(function() {
count.done++;
});
return deferred;
};
return $delegate;
});
答案 1 :(得分:1)
情节变浓。
我一直在根据@Bergi的优秀代码进行分析和跟踪代码,并注意到#31保持开放,所以我在那里添加了一个调试语句:
.config(function($provide) {
var count = window.promiseStats = {
open: 0,
done: 0,
promises: {}
};
$provide.decorator('$q', function($delegate) {
var defer = $delegate.defer;
$delegate.defer = function() {
count.open++;
var traceId = count.open;
if(traceId == 31) {
debugger;
}
var deferred = count.promises[traceId] = defer();
console.timeline('promise ' +traceId);
console.profile('promise '+traceId);
deferred.promise.finally(function() {
count.done++;
console.timelineEnd('promise ' +traceId);
console.profileEnd('promise '+traceId);
delete count.promises[traceId];
});
return deferred;
};
return $delegate;
});
})
这让我直接进入了一个角度核心模板请求,似乎有一种不同类型的承诺处理。
我还在努力评估这是否是一个问题。因为它似乎注销了一些专门的代码。