답변:
원하는 것을 수행하는 Plunk는 다음과 같습니다. http://plnkr.co/edit/TTlbSv?p=preview
아이디어는 약속과 직접 "그런 다음"기능을 사용하여 비동기 적으로 리턴 된 응답을 조작하고 액세스하는 것입니다.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
다음은 요청을 캐시하는 약간 더 복잡한 버전이므로 처음으로 만 만드십시오 ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ).
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
myService.async()
다양한 컨트롤러에서 여러 번 호출 $http.get()
하려면 첫 번째 요청에 대해서만 서비스를 구성 하고 모든 후속 요청은 첫 번째 호출에서 설정된 로컬 객체 배열을 반환합니다 myService.async()
. 즉, 실제로 하나만 만들면 JSON 서비스에 대한 여러 개의 불필요 한 요청을 피하고 싶습니다.
$scope.data = myService.async()
컨트롤러에서 직접 사용할 수도 있다고 생각합니다 .
간단하게하자. 그것은 간단합니다
promise
서비스 반품 (서비스에서 사용할 필요 없음 then
)then
컨트롤러에서 사용데모. http://plnkr.co/edit/cbdG5p?p=preview
var app = angular.module('plunker', []);
app.factory('myService', function($http) {
return {
async: function() {
return $http.get('test.json'); //1. this returns promise
}
};
});
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function(d) { //2. so you can use .then()
$scope.data = d;
});
});
app.factory
, 그리고 귀하의 코드에서 app.service
입니다. app.factory
이 경우에 가정 합니다.
비동기식이므로 $scope
ajax 호출이 완료되기 전에 데이터를 가져옵니다.
당신은 사용할 수 있습니다 $q
생성 서비스에 promise
다시 컨트롤러를주고, 컨트롤러는 내 결과를 얻을 수 then()
에 대한 호출 promise
.
당신의 봉사에서
app.factory('myService', function($http, $q) {
var deffered = $q.defer();
var data = [];
var myService = {};
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data = d;
console.log(d);
deffered.resolve();
});
return deffered.promise;
};
myService.data = function() { return data; };
return myService;
});
그런 다음 컨트롤러에서 :
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function() {
$scope.data = myService.data();
});
});
this.async = function() {
와 this.getData = function() {return data}
? 나는 당신이 무슨 뜻인지 알기를 바랍니다
deffered = $q.defer()
나는 myService.async () 두 개 이상의 시간을 호출 할 경우 myService.async 내부
$q.defer
는 AS $http
서비스가 이미 약속을 돌려줍니다. $http
오류가 반환 되면 반환 된 약속이 중단됩니다 . 또한 .success
and .error
메소드는 더 이상 사용되지 않으며 AngularJS 1.6에서 제거 되었습니다 .
tosh shimayama는 해결책이 있지만 $ http가 약속을 반환하고 약속이 가치를 반환 할 수 있다는 사실을 사용하면 단순화 할 수 있습니다.
app.factory('myService', function($http, $q) {
myService.async = function() {
return $http.get('test.json')
.then(function (response) {
var data = reponse.data;
console.log(data);
return data;
});
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.asyncData = myService.async();
$scope.$watch('asyncData', function(asyncData) {
if(angular.isDefined(asyncData)) {
// Do something with the returned data, angular handle promises fine, you don't have to reassign the value to the scope if you just want to use it with angular directives
}
});
});
커피 스크립트의 작은 데모 : http://plunker.no.de/edit/ksnErx?live=preview
귀하의 plunker가 내 방법으로 업데이트되었습니다 : http://plnkr.co/edit/mwSZGK?p=preview
내가 생각하는 훨씬 더 좋은 방법은 다음과 같습니다.
서비스:
app.service('FruitsManager',function($q){
function getAllFruits(){
var deferred = $q.defer();
...
// somewhere here use: deferred.resolve(awesomeFruits);
...
return deferred.promise;
}
return{
getAllFruits:getAllFruits
}
});
컨트롤러에서 간단히 사용할 수 있습니다.
$scope.fruits = FruitsManager.getAllFruits();
Angular는 자동으로 해결 된 것을에 awesomeFruits
넣습니다 $scope.fruits
.
나는 같은 문제가 있었지만 인터넷에서 서핑을 할 때 $ http가 기본적으로 약속을 되찾았다는 것을 이해했다. 그리고 나서 "data"를 반환 한 후 "then"으로 사용할 수있다. 코드를보십시오 :
app.service('myService', function($http) {
this.getData = function(){
var myResponseData = $http.get('test.json').then(function (response) {
console.log(response);.
return response.data;
});
return myResponseData;
}
});
app.controller('MainCtrl', function( myService, $scope) {
// Call the getData and set the response "data" in your scope.
myService.getData.then(function(myReponseData) {
$scope.data = myReponseData;
});
});
UI를 배열에 바인딩 할 때 길이를 0으로 설정하고 데이터를 배열로 푸시하여 동일한 배열을 직접 업데이트해야합니다.
이 대신 ( data
UI가 알지 못하는 다른 배열 참조를 설정 ) :
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data = d;
});
};
이 시도:
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data.length = 0;
for(var i = 0; i < d.length; i++){
data.push(d[i]);
}
});
};
다음은 새 배열 설정과 비우기 및 기존 배열 추가의 차이점을 보여주는 바이올린 입니다. 나는 당신의 plnkr을 작동시킬 수 없었지만 희망적으로 이것은 당신을 위해 작동합니다!
angular.copy(d, data)
작동합니다. 대상이 copy () 메소드에 제공되면 대상의 요소를 먼저 삭제 한 다음 소스에서 새 요소를 복사합니다.
이와 관련하여 나는 비슷한 문제를 겪었지만 Angular가 가져 오거나 게시하지 않았지만 타사 (내 경우에는 Chrome 확장 프로그램)가 만든 확장 기능을 사용했습니다.
내가 직면 한 문제는 Chrome 확장 프로그램이 반환되지 않으므로 then()
위의 솔루션에서 방법을 수행 할 수 없지만 결과는 여전히 비동기입니다.
그래서 내 솔루션은 서비스를 만들고 콜백을 진행하는 것입니다.
app.service('cookieInfoService', function() {
this.getInfo = function(callback) {
var model = {};
chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
model.response= response;
callback(model);
});
};
});
그런 다음 내 컨트롤러에서
app.controller("MyCtrl", function ($scope, cookieInfoService) {
cookieInfoService.getInfo(function (info) {
console.log(info);
});
});
이것이 다른 사람들이 같은 문제를 얻는 데 도움이되기를 바랍니다.
내가 읽은 http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS와는 범위에 직접 약속을 배치하는 대신 수동으로 해결 전달에 의해 우리의 컨트롤러 로직을 간소화 할 수있게 해준다 성공 콜백의 가치.]
너무 간단하고 편리합니다 :)
var app = angular.module('myApp', []);
app.factory('Data', function($http,$q) {
return {
getData : function(){
var deferred = $q.defer();
var promise = $http.get('./largeLoad').success(function (response) {
deferred.resolve(response);
});
// Return the promise to the controller
return deferred.promise;
}
}
});
app.controller('FetchCtrl',function($scope,Data){
$scope.items = Data.getData();
});
이 도움을 바랍니다
defrred.promise
함수가 아닙니다.
$scope.items = Data.getData();
Anglular에서 더 이상 사용되지 않습니다
나는 "약속적인"방식으로 일을하기 때문에 $ http를 사용하는 서비스 소비자는 응답의 압축을 푸는 방법을 "알아야한다"는 사실을 정말로 좋아하지 않는다.
난 그냥 뭔가를 호출하고 이전에 유사한 데이터 출력, 싶어 $scope.items = Data.getData();
되는 방식으로, 지금은 추천하지 않습니다 .
나는 잠시 동안 노력했지만 완벽한 솔루션을 얻지 못했지만 여기 내 최고의 장면이 있습니다 ( Plunker ). 누군가에게 유용 할 수 있습니다.
app.factory('myService', function($http) {
var _data; // cache data rather than promise
var myService = {};
myService.getData = function(obj) {
if(!_data) {
$http.get('test.json').then(function(result){
_data = result.data;
console.log(_data); // prove that it executes once
angular.extend(obj, _data);
});
} else {
angular.extend(obj, _data);
}
};
return myService;
});
그런 다음 컨트롤러 :
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = Object.create(null);
};
$scope.getData = function() {
$scope.clearData(); // also important: need to prepare input to getData as an object
myService.getData($scope.data); // **important bit** pass in object you want to augment
};
});
내가 이미 발견 할 수있는 결함은
getData
obj
많은 응용 프로그램에서 문제가되지는 않지만 객체 형식의 매개 변수 만 허용 할 수는 있지만 배열은 허용 할 수 있지만 아픈 제한입니다.$scope.data
를 = {}
객체 (본질적으로 $scope.clearData()
위의 것)로 만들거나 = []
배열로 만들거나 작동하지 않습니다 (우리는 이미 어떤 데이터가오고 있는지에 대해 뭔가를 가정해야합니다). 이 준비 단계 IN을 시도 getData
했지만 운이 없습니다.그럼에도 불구하고, 컨트롤러 "포장 풀기"상용구를 제거하는 패턴을 제공하며 DRY를 유지하면서 $ http에서 얻은 특정 데이터를 여러 곳에서 사용하려는 경우에 유용 할 수 있습니다.
서비스 응답을 캐싱하는 한, 여기에 내가 본 것보다 더 직설적으로 보이는 또 다른 버전이 있습니다.
App.factory('dataStorage', function($http) {
var dataStorage;//storage for cache
return (function() {
// if dataStorage exists returned cached version
return dataStorage = dataStorage || $http({
url: 'your.json',
method: 'GET',
cache: true
}).then(function (response) {
console.log('if storage don\'t exist : ' + response);
return response;
});
})();
});
이 서비스는 캐시 된 데이터 또는 $http.get
;
dataStorage.then(function(data) {
$scope.data = data;
},function(e){
console.log('err: ' + e);
});
아래 코드를 시도하십시오
컨트롤러 (PageCtrl)와 서비스 (dataService)를 분할 할 수 있습니다
'use strict';
(function () {
angular.module('myApp')
.controller('pageContl', ['$scope', 'dataService', PageContl])
.service('dataService', ['$q', '$http', DataService]);
function DataService($q, $http){
this.$q = $q;
this.$http = $http;
//... blob blob
}
DataService.prototype = {
getSearchData: function () {
var deferred = this.$q.defer(); //initiating promise
this.$http({
method: 'POST',//GET
url: 'test.json',
headers: { 'Content-Type': 'application/json' }
}).then(function(result) {
deferred.resolve(result.data);
},function (error) {
deferred.reject(error);
});
return deferred.promise;
},
getABCDATA: function () {
}
};
function PageContl($scope, dataService) {
this.$scope = $scope;
this.dataService = dataService; //injecting service Dependency in ctrl
this.pageData = {}; //or [];
}
PageContl.prototype = {
searchData: function () {
var self = this; //we can't access 'this' of parent fn from callback or inner function, that's why assigning in temp variable
this.dataService.getSearchData().then(function (data) {
self.searchData = data;
});
}
}
}());
then
있습니까?