.factory('ChartService', ['$http','$q',
function ChartService($http,$q) {
// interface
// implementation
var canceler = $q.defer();
function getTableData() {
return $http.post('http://202.429.115.52:9906/oo/api.php?request=getSubfunctionWiseHCAndSW').success(function (data) {
if (data.mm == "No Data Available"){
localData();
}
return data;
}).error(function(error){
alert("error")
canceler.resolve();
localData()
// console.log(error)
});
}
function localData(){
alert("loaddata")
return $http.get('vro/hcswc.json').success(function(response){
console.log(response+"==");
return response;
}).error(function(error){
console.log(error);
});
}
return {
getTableData:getTableData
}
}
]);
Error
XMLHttpRequest cannot load http://192.127.215.52:9906/api.php?request=getSubfunctionrection. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. The response had HTTP status code 404.
App.js // resolve Code
.state('app.vro', {
url: "/vro/:isfirstActiveState",
views: {
'menuContent': {
controller: "vrobCtrl",
templateUrl: 'vrob/vrob.html'
}
} ,
resolve: {
tableData:function(ChartService){
return ChartService.getTableData();
}
}
})
Hello
I am trying to get data form service .I have one condition while calling webservice .the condition is if I will get error then I get request from local in other words if I get any error from server than I need to read json file from local . I need to use resolve and call my service and use that data on controller .my localData is not returning data to resolve .what is the problem in my code ..
here is one example
http://plnkr.co/edit/0y9V0m2hmsUBRXoeyjig?p=preview
I am getting error correct but it should load data from local json .why it is not loading data from local json
It is an anti-pattern to use $q to manage $http requests but in this situation I don't know another way:
function getTableData() {
var deferred = $q.defer();
$http.post('http://202.129.215.52:9906/mondelez/api.php?request=getSubfunctionWiseHCAndSW')
.then(
// resolve callback
function(data) {
deferred.resolve(data.data)
return data.data;
},
// reject callback make different request
function(err) {
$http.get('data.json').success(function(response) {
deferred.resolve(response);
}).error(function(error) {
deferred.reject()
});
})
return deferred.promise;
}
DEMO
Related
I do not have the ability to change an endpoint, and it will return a 200 OK response with different data if it fails. How can I make it run the error function (The 2nd function in a then from a promise)?
MyService service:
self.getData = function() {
return $http.get('/api/controller/action').then(function(x) {
//This will be run even on failure. How can I call....
return x.data;
}, function(x) {
//......here, from the front-end, so that, the 2nd function in
//inside the 'then' in the controller is run.
//This code will currently never run as it never fails server side.
return x;
});
};
controller:
MyService.getData().then(function(x) {
//Success
}, function(x) {
//Failure
});
Use $q.reject, eg
return $http.get('/api/controller/action').then(function(x) {
if (x.data === 'some error condition') {
return $q.reject(x);
}
you can also check status of response you are getting after hitting the API ,
like, means there is some problem in API
if(status!=200){
// do something
}
I am using the following code with ngResource to retrieve a list of objects:
// Create the 'articles' service
angular.module('articles').factory('Articles', ['$resource', function($resource) {
// Use the '$resource' service to return an article '$resource' object
return $resource('../api/admins/:adminId/articles/:articleId', {
adminId: '#adminId'
}, {
update: {
method: 'PUT'
}
});
}]);
Articles are retrieved like so:
$scope.list = function() {
// Use the articles'query' method to send an appropriate GET request
Articles.query(
function(articles){
$scope.data.articles= articles;
},
function(error){
console.log(error);
}
);
};
When a user is logged in, all works fine: The client expects an array and that's what it gets.
But after a while when the login timed out, the server will return a 401 error with an object instead of an array. In fact, this is EXACTLY what is supposed to happen, but Angular throws the following error:
Error: [$resource:badcfg] Error in resource configuration.
Expected response to contain an array but got an object
The same problem occurs when a user retrieves a page that is forbidden (403).
Is there a way to resolve 401 and 403 request errors without getting an actual javascript error in Angular?
the query action of $resource by default expects an array to be returned from the server (see the docs).
You could use the transformResponse option for the query action to compensate for this like so:
return $resource('../api/admins/:adminId/articles/:articleId', {
adminId: '#adminId'
}, {
update: {
method: 'PUT'
},
query: {
transformResponse: function(data, headers) {
if(!angular.isArray(data)) {
return new Array(data);
}
return data;
}
}
});
Of course it would be much better to handle errors using the error callback or with an interceptor
I have an idea why it's not working, but not exactly how to fix this, and I've looked at the various similar questions/answers on SO but I can not fix my issue.
I am trying to call a service on page load to list a table of data, or let's just call this a list of urls.
The model would simply be { urls } would should return an array of urls, where in the future I'd use ng-repeat.
My controller:
function UrlListCtrl($scope, UrlService){
$scope.urls = UrlService.getUrls();
}
Service:
function UrlService($http) {
return {
getUrls: getUrls
}
function getUrls() {
console.log('Fetching Urls...');
return $http.get('urls/get')
.then(function(response) {
console.log('response:', response.data);
this.urlsResults = response.data;
});
}
}
The service does run, however it doesn't update the view. How can I fix this?
$http.get() is an async operation that returns a promise. You have to wait for this promise to be fulfilled, and then you can get the data from the response.
In your code $scope.urls = UrlService.getUrls(); was assigning the promise, and not it's results to $scope.urls, and the view was never updated when the operation ended.
Controller:
function UrlListCtrl($scope, UrlService){
UrlService.getUrls().then(function(response) {
$scope.urls = response.data;
});
}
Service:
function UrlService($http) {
return {
getUrls: getUrls
}
function getUrls() {
console.log('Fetching Urls...');
return $http.get('urls/get');
}
}
I am using Parse.com as a backend for an Ionic Framework App which means I have to monitor the network activity. I can handle online / offline by using this guide. However, I need a more 'app wide' solution checks on each call. I'm currently getting errors when there is no network as the response from the server is null causing the following error:
Error: null is not an object (evaluating 'response.error')
My question is two fold:
Is it possible to create a network factory / service that I can inject into my ParseFactory to check and notify the user that their network is insufficient.
Handle a null response object in this code:
ParseFactory.provider('Programme/').get($stateParams.loadProgramme).success (function(data){
// do something with success...
}).error(function(response){
$rootScope.$emit('errorEvent',
{"message" : "Unable to load Programme. Please check your connection", "errorObject": response.error}
);
});
My Factory for Parse calls is below:
.factory('ParseFactory',['$http','PARSE_CREDENTIALS',function($http,PARSE_CREDENTIALS){
var baseUrl = 'https://api.parse.com/1/classes/';
return {
provider:function(type, queryParam, queryValue) {
console.log(queryValue);
whereQuery = {}
whereQuery[queryParam] = queryValue;
var masterQuery = {'userId': masterKey};
return {
getAll:function(){
return $http.get(getUrl(type),getParams(whereQuery));
},
getMasters:function(){
return $http.get(getUrl(type),getParams(masterQuery));
},
get:function(id){
return $http.get(getUrl(type)+id,getParams());
},
create:function(data){
return $http.post(getUrl(type),data,getParams());
},
edit:function(id,data){
return $http.put(getUrl(type)+id,data,getParams());
},
delete:function(id){
return $http.delete(getUrl(type)+id,getParams());
}
}
function getUrl(type) {
return baseUrl+type;
}
function getParams(user) {
return {
timeout : 5000,
headers:{
'X-Parse-Application-Id': PARSE_CREDENTIALS.APP_ID,
'X-Parse-REST-API-Key':PARSE_CREDENTIALS.REST_API_KEY,
'X-Parse-Session-Token': Parse.User.current()._sessionToken,
'Content-Type':'application/json'
},
params: {
where: user,
// limit: 2,
// count: 1
// include: "something"
}
}
}
}
}
}])
Use a $http interceptor. All requests using $http are passed through interceptors, so by using interceptors you can apply global handling for successful or unsuccessful requests and responses.
For example, this interceptor cancels a request if the network connection is not available and emits an event when an empty response is received:
app.factory('networkActivityInterceptor', function($rootScope, $q, networkMonitorService) {
return {
'request': function(config) {
var canceller = $q.defer();
config.timeout = canceller.promise;
if (!networkMonitorService.hasNetworkConnection()) {
// cancels the request if there is no network connection
canceller.resolve();
}
// otherwise, let the request go through as normal
return config;
},
'response': function(response) {
// handle a null/empty response
if (!response.data) {
$rootScope.$emit('errorEvent', {
message: 'Unable to load...',
errorObject: response.error
});
}
return response;
},
'responseError': function(response) {
// the response handling above could also be done in the responseError
// handler which is hit when an error HTTP code is returned. (example: 404, 500)
// this depends on what your server is configured to return.
// note that in a responseError handler you must return a rejected promise
// (i.e. return $q.reject(response);)
}
};
});
Substitute networkMonitorService.hasNetworkConnection() for your app's network activity logic.
I am not able to get chained promises to work as per RSVP documentation. I have a case where I am trying to fetch some data from the server. If for some reason an error occurs, I want to fetch the data from a local file.
I am trying to chain promises for that.
I have created a simplified example. The below example will give an output but is not what I want.
http://emberjs.jsbin.com/cobax/3
App.IndexRoute = Em.Route.extend({
model: function() {
return Ember.$.getJSON('http://test.com/search')
.then(undefined, function(errorObj, error, message) {
return new Promise(function(resolve, reject) {
resolve(model);
}).then(function(response) {
console.info(response.articles);
return response.articles;
});
});
}
});
This example is what I want but it wont call the final 'then'.
http://emberjs.jsbin.com/cobax/3
App.IndexRoute = Em.Route.extend({
model: function() {
return Ember.$.getJSON('http://test.com/search')
.then(undefined, function(errorObj, error, message) {
return new Promise(function(resolve, reject) {
resolve(model);
});
})
.then(function(response) {
console.info(response.articles);
return response.articles;
});
}
});
Basically I want to handle the server/local response from the last 'then' method. I also want keep all the callbacks in a single level.
What is the error in the second code snipped?
Update
As #marcio-junior mentioned, the jquery deferred was the issue. Here is the fixed bin from him.
http://jsbin.com/fimacavu/1/edit
My actual code doesn't return a model object, it makes another getJSON request to a json file. I can't replicate this in a bin as I dont think js bin allows us to host static files. Here is the code but it wont work. It fails due to some js error.
App.IndexRoute = Em.Route.extend({
model: function() {
var cast = Em.RSVP.Promise.cast.bind(Em.RSVP.Promise);
return cast(Ember.$.getJSON('http://test.com/search'))
.then(undefined, function(errorObj, error, message) {
//return Em.RSVP.resolve(model);
return cast(Ember.$.getJSON('data.json'));
})
.then(function(response) {
console.info(response.articles);
return response.articles;
});
}
});
Can you help me with this? These promises are a bit tricky to understand.
Here is the error stack I see
XMLHttpRequest cannot load http://test.com/search. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. localhost/:1
Error while loading route: index ember-canary-1.7.0.js:3916
logToConsole ember-canary-1.7.0.js:3916
defaultActionHandlers.error ember-canary-1.7.0.js:39681
triggerEvent ember-canary-1.7.0.js:39763
trigger ember-canary-1.7.0.js:42317
Transition.trigger ember-canary-1.7.0.js:42162
(anonymous function) ember-canary-1.7.0.js:42017
invokeCallback ember-canary-1.7.0.js:10498
publish ember-canary-1.7.0.js:10168
publishRejection ember-canary-1.7.0.js:10596
(anonymous function) ember-canary-1.7.0.js:15975
DeferredActionQueues.flush ember-canary-1.7.0.js:8610
Backburner.end ember-canary-1.7.0.js:8082
(anonymous function)
You are returning a RSVP promise to a jquery deferred. And jquery deferreds doesn't have the feature of fulfill a rejected promise. So you need to update your sample to use Em.RSVP.Promise.cast(deferred), to transform a deferred in a RSVP promise, which implements the promises/a+ spec and does what you want:
App.IndexRoute = Em.Route.extend({
model: function() {
return Em.RSVP.Promise.cast(Ember.$.getJSON('http://test.com/search'))
.then(undefined, function() {
return getDefaultData();
})
.then(function(response) {
console.info(response.articles);
return response.articles;
});
}
});
Your updated jsbin
Here is the final route code I used. Its simply checks for the my apps api for the results. If its not present, I take the static results from a sample json file. The parsing of the response happens at the end irrespective of where it came from.
var App.IndexRoute = Ember.Route.extend({
model: function() {
var cast = Em.RSVP.Promise.cast.bind(Em.RSVP.Promise);
return cast(Ember.$.getJSON('http://test.com/search'))
.then(undefined, function(error) {
console.info(error);
return Ember.$.getJSON('assets/data.json');
})
.then(function(response) {
console.info(response);
return JSON.parse(response);
});
}
});