您好我过去两天尝试根据异步http服务的响应来创建视图。但它对我不起作用。任何人都可以帮助我吗?
这里有基本概念的代码,但原始代码有点不同:
var myApp = angular.module('app', []);
myApp.directive('dashboard',['service1',function(service1){
return {
templateUrl: 'sometemplate.html',
controller: function ($scope) {
$scope.data = {};
service1.get('keyXXX');
$scope.$watch(service1.data['keyXXX'],function(n,o){
//how to make this work???
//I always get null or it would not get executed at all
});
}
}
}])
.service('service1',['someAsyncservice',function(someAsyncservice){
var _s={
data:{},
get:function(key){
if(this.data[key]==undefined)
{
this.data[key]={status:"loading",data:{}};
}
someAsyncservice().then(function(result){
_s[key].data=result;
_s[key].status="success";
});
}
}
return _s;
}])
答案 0 :(得分:1)
这是一个扩展示例,主要使用您的原始代码,展示了如何完全不使用$apply
或$watch
。只需使用$q
,您就可以绕过前两个函数可能产生的大部分问题:
(function (app, ng) {
'use strict';
app.controller('TestCtrl', ['$scope', 'RefreshViewService', function ($scope, RefreshViewService) {
$scope.key = 'key_A';
$scope.refresh = function refresh(key) {
$scope.busy = true;
RefreshViewService.refresh(key).then(function () {
$scope.busy = false;
});
};
}]);
app.directive('dashboard', ['service1', function(service1) {
return {
template: '<pre><strong>{{ key }}</strong>: {{ data|json }}</pre>',
scope: {
key: '@'
},
controller: function ($scope) {
// use currently provided data
$scope.data = service1.get($scope.key);
// load data
service1.load($scope.key).then(function (response) {
$scope.data = response;
});
}
};
}]);
app.service('service1', ['$q', 'someAsyncService', function($q, someAsyncService){
var data = {}, loading = {};
return {
/**
* returns the currently available data for `key`
*
* @param key
* @returns {*}
*/
get: function (key) {
if(data[key] === undefined) {
data[key] = {
status: 'loading',
data: {}
};
}
return data[key];
},
/**
* async load data for `key`
*
* @param key
* @returns {*}
*/
load: function(key){
// clear previous data
if (loading[key] === undefined) {
data[key].status = 'loading';
data[key].data = {};
}
return $q(function (resolve, reject) {
// only run if not already loading
if (loading[key] === undefined) {
loading[key] = someAsyncService(key).then(function(result) {
data[key].status = 'success';
data[key].data = result;
delete loading[key];
resolve(data[key]);
});
}
return loading;
});
}
};
}]);
/**
* mock refresh service
*/
app.service('RefreshViewService', ['service1', function(service1) {
return {
refresh: function (key) {
return service1.load(key);
}
};
}]);
/**
* mock async service
*/
app.service('someAsyncService', ['$q', '$timeout', function ($q, $timeout) {
return function(key) {
return $q(function (resolve, reject) {
$timeout(function () {
resolve({ 'requested key': key, 'foo': Math.floor(Math.random() * 100) });
}, 500 + Math.random() * 3000);
});
};
}]);
})(angular.module('app', []), angular);
&#13;
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div data-ng-app="app" class="container">
<div data-ng-controller="TestCtrl">
<div class="radio">
<label>
<input type="radio" data-ng-model="key" data-ng-disabled="busy" value="key_A"> key A
</label>
<label>
<input type="radio" data-ng-model="key" data-ng-disabled="busy" value="key_B"> key B
</label>
</div>
<button class="btn btn-primary" data-ng-click="refresh(key)" data-ng-disabled="busy">Refresh</button>
<span data-ng-show="busy">loading...</span>
</div>
<hr>
<dashboard key="key_A"></dashboard>
<dashboard key="key_A"></dashboard>
<dashboard key="key_B"></dashboard>
&#13;
虽然可能还有其他(更好)的方法,但只需将观看的值包装在一个函数中即可。 E.g:
$watch(function() { return service1.data['keyXXX']; }, ...
但请注意,只有当someAsyncservice
实际上触发摘要周期时才能使用此功能(例如,使用$q
等)!
答案 1 :(得分:0)
我没有真正测试过,但尝试:
$scope.$watch(function(){return service1.data['keyXXX']},function(n,o){
//how to make this work???
//I always get null or it would not get executed at all
});