假设你有:
function myPromise() {
// using some promise lib other than $q, like Q or bluebird
var defer = Q.defer();
defer.resolve('John');
return defer.promise;
}
然后你有类似的东西:
function foo() {
return myPromise().then(function (name) {
return name + ' Smith';
});
}
foo().then(function (name) {
$scope.$apply(function () { // or can use $timeout
console.log('after foo');
$scope.text = 'Hey ' + name;
});
});
有没有办法修改foo,以便foo块之后的自动包装在$ scope中。$ apply()?即我们可以只有:
foo().then(function (name) {
console.log('after foo');
$scope.text = 'Hey ' + name;
// $scope.$apply() is automatically called after this block is executed
});
我问的原因是我正在开发一个API,其中用户将进行多个这些foo调用,如果在foo promise结算后自动触发摘要周期,它将大大减少用户的代码。我知道我可以使用回调来实现这一点,但我希望有一种更简洁的方式来使用promises。
我的预感是解决方案在于将非$ q承诺包含在$ q承诺中......
答案 0 :(得分:1)
目前Angular的结束无法做到这一点。从另一个方向来看,Q promise库也没有公开这个钩子。
所以,你有两个选择:
then
方法,这将起作用,因为Q的结构如何,但有点危险,并且可能在Q的未来版本中中断(因此在升级时要小心)。 / LI>
我强烈建议使用后者并使用允许您设置调度程序的promise库。它有更好的支持,并没有创造超额承诺。但是,如果您想在第一个方法中使用第一个方法:
var oldThen = Q.Promise.prototype.then; // reference `then`
Q.Promise.prototype.then = function(){
return oldThen.apply(this, arguments). // decorate
then(function(value){
$rootScope.$evalAsync(function(){}); // schedule digest
return value; // keep value
},function(err){
$rootScope.$evalAsync(function(){}); // schedule digest
return $q.reject(err); // keep rejection
});
};
基本上,如果在完成后没有安排一个摘要,我们会在此处推迟每个Q调度摘要。关于它的工作原理,您可以阅读this question and answer。
(信用通知 - 我从我参与的讨论中获取了上述代码。上面的大部分代码都是由我编写的,但有些是由Angular的杰夫克罗斯编写的,所以对他也很有信心)
答案 1 :(得分:0)
我能够通过将我的API函数包装在$ timeout块中来触发摘要周期,例如
function foo() {
return $timeout(function () {
return myPromise().then(function (name) {
return name + ' Smith';
});
});
}