AngularJS: преобразование ответа в $resource с помощью настраиваемой службы
Я пытаюсь украсить возвращаемые данные из ресурса angular $данными из пользовательской службы.
Мой код:
angular.module('yoApp')
.service('ServerStatus', ['$resource', 'ServerConfig', function($resource, ServerConfig) {
var mixinConfig = function(data, ServerConfig) {
for ( var i = 0; i < data.servers.length; i++) {
var cfg = ServerConfig.get({server: data.servers[i].name});
if (cfg) {
data.servers[i].cfg = cfg;
}
}
return data;
};
return $resource('/service/server/:server', {server: '@server'}, {
query: {
method: 'GET',
isArray: true,
transformResponse: function(data, header) {
return mixinConfig(angular.fromJson(data), ServerConfig);
}
},
get: {
method: 'GET',
isArray: false,
transformResponse: function(data, header) {
var cfg = ServerConfig.get({server: 'localhost'});
return mixinConfig(angular.fromJson(data), ServerConfig);
}
}
});
}]);
Кажется, я делаю что-то неправильно в отношении инъекции зависимостей. Данные, возвращаемые с ServerConfig.get(), отмечены как неразрешенные.
Я получил эту работу в контроллере, где я делаю преобразование с помощью
ServerStatus.get(function(data) {$scope.mixinConfig(data);});
Но я предпочел бы сделать украшение на службе. Как я могу сделать эту работу?
Ответы
Ответ 1
Невозможно использовать transformResponse для украшения данных данными из асинхронной службы.
Я опубликовал решение http://jsfiddle.net/maddin/7zgz6/.
Вот псевдокод, объясняющий решение:
angular.module('myApp').service('MyService', function($q, $resource) {
var getResult = function() {
var fullResult = $q.defer();
$resource('url').get().$promise.then(function(data) {
var partialPromises = [];
for (var i = 0; i < data.elements.length; i++) {
var ires = $q.defer();
partialPromisses.push(ires);
$resource('url2').get().$promise.then(function(data2) {
//do whatever you want with data
ires.resolve(data2);
});
$q.all(partialPromisses).then(function() {
fullResult.resolve(data);
});
return fullResult.promise; // or just fullResult
}
});
};
return {
getResult: getResult
};
});
Ответ 2
Ну, на самом деле можно украсить данные для ресурса асинхронно, но не с помощью метода transformResponse
. Необходимо использовать interceptor
.
Вот быстрый пример.
angular.module('app').factory('myResource', function ($resource, $http) {
return $resource('api/myresource', {}, {
get: {
method: 'GET',
interceptor: {
response: function (response) {
var originalData = response.data;
return $http({
method: 'GET',
url: 'api/otherresource'
})
.then(function (response) {
//modify the data of myResource with the data from the second request
originalData.otherResource = response.data;
return originalData;
});
}
}
});
Вы можете использовать любой сервис/ресурс вместо $http
.
Update:
Из-за того, что реализован перехватчик ресурсов angular $$, указанный выше код будет только украшать данные, возвращаемые $prom, и в некотором смысле нарушает некоторые из концепций $resource, в частности.
var myObject = myResource.get(myId);
Только это сработает.
var myObject;
myResource.get(myId).$promise.then(function (res) {
myObject = res;
});