Как правильно использовать HTTP.GET в AngularJS? В частности, для внешнего вызова API?
У меня есть следующий код в контроллере .js,
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = dataService.getData();
});
Но, я думаю, я, вероятно, ошибаюсь в проблеме CORS. Не могли бы вы указать мне правильный способ сделать этот звонок? Большое спасибо!
Ответы
Ответ 1
Во-первых, ваш обработчик success()
просто возвращает данные, но не возвращается вызывающему абоненту getData()
, поскольку он уже находится в обратном вызове. $http
- это асинхронный вызов, который возвращает $promise
, поэтому вам необходимо зарегистрировать обратный вызов, когда данные доступны.
Я бы рекомендовал искать Promises и $q library в AngularJS, так как это лучший способ обойти асинхронные вызовы между службами.
Для простоты здесь ваш же код переписан с обратным вызовом функции, предоставляемым вызывающим контроллером:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function(callbackFunc) {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, call our callback
callbackFunc(data);
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData(function(dataResponse) {
$scope.data = dataResponse;
});
});
Теперь $http
на самом деле уже возвращает $prom, поэтому его можно переписать:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
// $http() returns a $promise that we can add handlers with .then()
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(dataResponse) {
$scope.data = dataResponse;
});
});
Наконец, есть более эффективные способы настройки службы $http
для обработки заголовков для вас с помощью config()
для настройки $httpProvider
. Оформляйте документацию $http для примеров.
Ответ 2
Я предлагаю вам использовать Promise
myApp.service('dataService', function($http,$q) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
deferred = $q.defer();
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, we can resolve promise and we can access it in controller
deferred.resolve();
}).error(function(){
alert("error");
//let the function caller know the error
deferred.reject(error);
});
return deferred.promise;
}
});
поэтому в вашем контроллере вы можете использовать метод
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
promises являются мощной функцией angularjs, и это удобно, если вы хотите избежать обратных вызовов вложенности.
Ответ 3
Не нужно обещать с $http, я использую его только с двумя возвратами:
myApp.service('dataService', function($http) {
this.getData = function() {
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data;
}).error(function(){
alert("error");
return null ;
});
}
});
В контроллере
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
Ответ 4
Попробуйте это
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
Просто установка useXDomain = true недостаточно. Запрос AJAX также отправляется с заголовком X-Requested-With, который указывает их как AJAX. Удаление заголовка необходимо, поэтому сервер не отклоняет входящий запрос.
Ответ 5
Итак, вам нужно использовать то, что мы называем обещанием. Читайте, как angular обрабатывает его здесь, https://docs.angularjs.org/api/ng/service/ $q. Превращает нашу поддержку $http promises по сути, поэтому в вашем случае мы сделаем что-то вроде этого,
(function() {
"use strict";
var serviceCallJson = function($http) {
this.getCustomers = function() {
// http method anyways returns promise so you can catch it in calling function
return $http({
method : 'get',
url : '../viewersData/userPwdPair.json'
});
}
}
var validateIn = function (serviceCallJson, $q) {
this.called = function(username, password) {
var deferred = $q.defer();
serviceCallJson.getCustomers().then(
function( returnedData ) {
console.log(returnedData); // you should get output here this is a success handler
var i = 0;
angular.forEach(returnedData, function(value, key){
while (i < 10) {
if(value[i].username == username) {
if(value[i].password == password) {
alert("Logged In");
}
}
i = i + 1;
}
});
},
function() {
// this is error handler
}
);
return deferred.promise;
}
}
angular.module('assignment1App')
.service ('serviceCallJson', serviceCallJson)
angular.module('assignment1App')
.service ('validateIn', ['serviceCallJson', validateIn])
}())
Ответ 6
Использование Google Finance в качестве примера для получения последней цены закрытия и обновленной даты и времени. Вы можете посетить YouTiming.com для выполнения во время выполнения.
Услуга:
MyApp.service('getData',
[
'$http',
function($http) {
this.getQuote = function(ticker) {
var _url = 'https://www.google.com/finance/info?q=' + ticker;
return $http.get(_url); //Simply return the promise to the caller
};
}
]
);
Контроллер:
MyApp.controller('StockREST',
[
'$scope',
'getData', //<-- the service above
function($scope, getData) {
var getQuote = function(symbol) {
getData.getQuote(symbol)
.success(function(response, status, headers, config) {
var _data = response.substring(4, response.length);
var _json = JSON.parse(_data);
$scope.stockQuoteData = _json[0];
// ticker: $scope.stockQuoteData.t
// last price: $scope.stockQuoteData.l
// last updated time: $scope.stockQuoteData.ltt, such as "7:59PM EDT"
// last updated date & time: $scope.stockQuoteData.lt, such as "Sep 29, 7:59PM EDT"
})
.error(function(response, status, headers, config) {
console.log('@@@ Error: in retrieving Google Finance stock quote, ticker = ' + symbol);
});
};
getQuote($scope.ticker.tick.name); //Initialize
$scope.getQuote = getQuote; //as defined above
}
]
);
HTML:
<span>{{stockQuoteData.l}}, {{stockQuoteData.lt}}</span>
В верхней части домашней страницы YouTiming.com я разместил заметки о том, как отключить политику CORS для Chrome и Safari.
Ответ 7
При вызове обещания, определенного в службе или в factory, обязательно используйте службу, поскольку я не мог получить ответ от обещания, определенного в factory. Вот как я называю обещание, определенное в сервисе.
myApp.service('serverOperations', function($http) {
this.get_data = function(user) {
return $http.post('http://localhost/serverOperations.php?action=get_data', user);
};
})
myApp.controller('loginCtrl', function($http, $q, serverOperations, user) {
serverOperations.get_data(user)
.then( function(response) {
console.log(response.data);
}
);
})