我正在尝试使用angular和es6 promise构建一个下钻列表。不使用promise我的代码就像在下面的代码片段中演示一样。每次单击父项时,它都会扩展子项(为简单起见,只是样本中的foo和bar)。
angular.module('demo', [])
.controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
$scope.entities = dataSvc.loadInitialData();
}])
.directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
return {
restrict: 'A',
scope: {
entities: '='
},
controller: function($scope) {
$scope.load = function() {
this.entity.subEntities = dataSvc.load();
};
},
compile: function(element) {
var contents = element.contents().remove();
var compiled = null;
return function(scope, element) {
if (!compiled) {
compiled = $compile(contents);
}
compiled(scope, function(clone) {
element.append(clone);
});
};
},
template:
'<li ng-repeat="entity in entities">' +
'<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
'<ul drill-down entities="entity.subEntities"></ul>' +
'</li>'
};
}])
.service('dataService', function() {
this.loadInitialData = function() {
return [
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
];
};
this.load = function() {
return this.loadInitialData();
};
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
<ul drill-down entities="entities"></ul>
</div>
&#13;
然而,当我将其更改为使用promise时,出现问题:现在您必须双击该元素以展开它,并且范围也会混乱。
差别主要在于服务和指令控制器中的load
函数。到目前为止,我还没有真正研究过角色的$q
api,但为什么我只能使用诺言呢? $q
中有什么神奇的东西吗?
angular.module('demo', [])
.controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
$scope.entities = dataSvc.loadInitialData();
}])
.directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
return {
restrict: 'A',
scope: {
entities: '='
},
controller: function($scope) {
$scope.load = function() {
var s = this;
dataSvc.load().then(function(res) {
s.entity.subEntities = res;
});
};
},
compile: function(element) {
var contents = element.contents().remove();
var compiled = null;
return function(scope, element) {
if (!compiled) {
compiled = $compile(contents);
}
compiled(scope, function(clone) {
element.append(clone);
});
};
},
template:
'<li ng-repeat="entity in entities">' +
'<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
'<ul drill-down entities="entity.subEntities"></ul>' +
'</li>'
};
}])
.service('dataService', function() {
this.loadInitialData = function() {
return [
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
];
};
this.load = function() {
return new Promise(function(resolve, reject) {
resolve([
{
name: 'foo',
subEntities: []
},
{
name: 'bar',
subEntities: []
}
]);
});
};
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
<ul drill-down entities="entities"></ul>
</div>
&#13;
答案 0 :(得分:2)
这将要求ES6承诺公开用于设置调度程序的挂钩(如蓝鸟承诺)或公开&#34; post-then&#34;钩子 - 它们都不是公开的。
您必须通过以下方式强制执行ES6对$q
的承诺:
$q.when(dataSvc.load()).then(...
或者,您可以编写一个帮助程序将其绑定到范围:
var withDigest = function(fn){
fn().then(function(){
$rootScope.evalAsync(angular.noop); // schedule digest if not scheduled
});
};
然后做:
withDigest(function(){
return dataSvc.load().then(...
});
答案 1 :(得分:0)
也许是因为你在回调函数
之外的角度世界之外dataSvc.load().then(function(res) {
s.entity.subEntities = res;
});
这不是最佳解决方案,但如果您致电$scope.$apply()
,它应该有效:
dataSvc.load().then(function(res) {
s.entity.subEntities = res;
$scope.$apply()
});
jsfiddle with $ scope。$ apply():)
http://jsfiddle.net/Fieldset/xdxprzgw/
最好的解决方案是使用$ q。
来自angularjs doc:
&#39; $ q与角度中的$ rootScope.Scope Scope模型观察机制集成,这意味着更快地将分辨率或拒绝传播到模型中,避免不必要的浏览器重绘,这将导致UI闪烁。&# 39;&#39;