Exclude specific url from loading interceptor in AngularJS [duplicate] - angularjs

In the documentation (version 1.1) of AngularJS about interceptors, the interceptor functions all return something like this
return response || $q.when(response);
However, in my app, 'response' is always defined, so $q.when(response) is never executed.
So the question is in what situation will the 'response' be undefined and what will
$q.when(response) // == $q.when(null)
do! because response is undefined/null ?

$q.when(promise) → promise
$q.when(nonPromise) → a new promise, that will asynchronously resolve to the given value nonPromise.
Lets see what is $q.when:
$q.when = function (foreignPromise) {
var deferred = $q.defer();
foreignPromise.then(function (data) {
deferred.resolve(data);
$rootScope.$digest();
}, function (reason) {
deferred.reject(reason);
$rootScope.$digest();
});
return deferred.promise;
}
Factory return $q.when(data)
As we can see $q.when receives promise or nonPromise and wrap it with.
Factory example:
fessmodule.factory('Data', ['$resource','$q', function($resource, $q) {
var data = [
{
"PreAlertInventory": "5.000000",
"SharesInInventory": "3.000000",
"TotalSharesSold": "2.000000",
"TotalMoneySharesSold": "18.000000",
"TotalSharesBought": "0.000000",
"TotalShareCost": "0.000000",
"EstimatedLosses": "0.000000"
}
];
var factory = {
query: function (selectedSubject) {
return $q.when(data);
}
}
return factory;
}]);
Now we can call it from controller:
Data.query()
.then(function (result) {
$scope.data = result;
}, function (result) {
alert("Error: No data returned");
});
Demo Fiddle
Factory returns $q.when(data) || data
From this example we return promise. So lets change it a bit:
Instead return $q.when(data); we will write:
return $q.when(data) || data;
It will work as well. But not vice versa.
As I understand Angular knows that controller waits from Data service the promise and above mentioned statement will use 1st off $q.when(data).
Demo 2 Fiddle
Factory returns data || $q.when(data)
Now lets call our Data service by this way:
$scope.data = Data.query();
No promises, the call is sync.
Out factory seems like:
fessmodule.factory('Data', ['$resource','$q', function($resource, $q) {
var data = [
{
"PreAlertInventory": "5.000000",
"SharesInInventory": "3.000000",
"TotalSharesSold": "2.000000",
"TotalMoneySharesSold": "18.000000",
"TotalSharesBought": "0.000000",
"TotalShareCost": "0.000000",
"EstimatedLosses": "0.000000"
}
];
var factory = {
query: function (selectedSubject) {
return data || $q.when(data);
}
}
return factory;
}]);
Demo 3 Fiddle
My Conclusion
The return data || $q.when(data) means that our service can return single value or promise. But since we know what type of data our service returns , there is no sense in this statement. Or data or promise.

The statements:
return config || $q.when(config);
//AND
return response || $q.when(response);
Are shown in V1.1 of the Documentation of interceptors. It was removed from later versions of the documentation. I think it was a misguided attempt to document that interceptor functions can return either a value or a promise.
The statements otherwise make no sense as config and response always have a reference.

Related

AngularJS : How to initialize service with async data and inject it into depend service

I have a similar situation like in AngularJS : Initialize service with asynchronous data, but I need to inject my base service with asynchronous data into depend services. It looks like this:
Base service:
angular.module('my.app').factory('baseService', baseService);
baseService.$inject = ['$http'];
function baseService($http) {
var myData = null;
var promise = $http.get('api/getMyData').success(function (data) {
myData = data;
});
return {
promise: promise,
getData: function() {
return myData;
}};
}
Dependent service (in which I inject base service)
angular.module('my.app').factory('depentService', depentService);
depentService.$inject = ['baseService'];
function depentService(baseService) {
var myData = baseService.getData();
....
return {...};
}
Route:
angular.module('my.app', ["ngRoute"])
.config(function ($routeProvider) {
$routeProvider.when('/',
{
resolve: {
'baseService': function (baseService) {
return baseService.promise;
}
}
});
});
But nothing happens, baseService.getData() still returns null (coz async api call still in progress). Seems like my ngRoute config is invalid, but I cant indicate any controller/template into it.
How can I correctly resolve my baseService and get data in Depend service?
Dependent services should work with promises and return promises:
angular.module('my.app').factory('depentService', depentService);
depentService.$inject = ['baseService'];
function depentService(baseService) {
̶v̶a̶r̶ ̶m̶y̶D̶a̶t̶a̶ ̶=̶ ̶b̶a̶s̶e̶S̶e̶r̶v̶i̶c̶e̶.̶g̶e̶t̶D̶a̶t̶a̶(̶)̶;̶
var promise = baseService.promise;
var newPromise = promise.then(function(response) {
var data = response.data;
//...
var newData //...
return newData;
});
return newPromise;
}
To attempt to use raw data risks race conditions where the dependent service operates before the primary data returns from the server.
From the Docs:
The .then method returns a new promise which is resolved or rejected via the return value of the successCallback, errorCallback (unless that value is a promise, in which case it is resolved with the value which is resolved in that promise using promise chaining).
— AngularJS $q Service API Reference - The Promise API

Angular directive without timeout service does not work

In angularJS, I have written a directive to display data. This data is fetched by a http service from remote database.
If I apply below timeout service in code, then result is displayed on the html page as http service returns in one second.
$timeout(function () {
$scope.treeRoot = $scope.$eval('serviceResult') || {};
}, 1000);
If i do not use timeout service, then page does not show any data because $scope.treeRoot is empty e.g.
$scope.treeRoot = $scope.$eval('serviceResult') || {};
In production, the http service can take time more than one second to return, is there any generic solution.
You should use Angular's promises or $http service which allows to return a promise.
After the promise, e.g. $http request, is resolved, you can populate $scope.treeRoot with the results.
Let me know if that helps.
AS suggested in one answer you have to use the $http promises and capture the result in response.
Here is an example with some code.
Service:
app.factory('myService', ['$http',
function($http){
var obj = {};
obj.get = function (q) {
return $http.get('/your_get_url')
};
obj.post = function (q, object) {
return $http.post('/your_post_url', object)
};
return obj;
}
]);
In your controller,
allControllers.controller('changePasswordController', ['$scope','myService',
function($scope,myService) {
myService.get().then(function (result) {
$scope.treeRoot = 'use your result here'
},function error(result)
{
console.log(result)
})
}
])
This replaces your timeout issue.

how to retrieve ajax response value from service?

I am using 2 service in controller
First Service is to get AjaxResponse where logic to fetching the response is mentioned
The second Service calls the first service to make Http request and get result and then, in turn, return it to the controller
Ctrl Dependency injected firstService,secondService
this.getService = secondService.getData(param);
First Service--> firstService
this.httpResponse(param){
var re = $http.get(param);
return re.then(success,fail);
}
function success(data){
return data;
}
function fail(data){
console.log(data);
}
Second Service (Dependency injection of First Service)
function secondService(firstService){
this.getData = function(param){
return firstService.httpResponse(param);
};
}
this.getService is coming as undefined, all the call are going properly.
Even tried the following code:
secondService.getData(param).then(function(data){console.log(data);});
That doesn't help either.
You should chain the promises in these kinds of situations.
First, you define your service. It should contain two distinct functions. As an example, I did a GET and a POST.
angular.module("myApp",[]).factory("SharedServices", function($http) {
return {
getItem: function() {
return $http.get('path/to/api');
},
postItem: function(payload) {
return $http.post('path/to/api', payload);
}
};
});
Then, reference the service in your controller. getItem() will return a promise, where you can use it using .then to call your second service in the success callback.
angular.module("myApp",[]).controller("MainCtrl", function($scope, SharedServices) {
SharedServices.getItem().then(function(response) {
//success, got something
//call the second part
var payload = { myPayload: response.data.someItem };
SharedServices.postItem(payload).then(function(response) {
//success
}, function(response) {
//an error has occurred to the second call--POST
});
}, function(response) {
//an error occurred to the first call--GET
});
});
Used Callback to get the result.It is similar to deferred(promise)

Return value of a promise to a function in AngularJS

I have a problem with outputting the values of a promise function.
$scope.getTeacher = function(teacherAbr) {
var promise = dataService.getTeacher(teacherAbr);
var testje = promise.then(function(payload) {
return payload;
});
return testje; // outputs an d object, not the direct payload values
};
The output of this controller function is this:
However, when I'm doing testje.$$state it returns undefined. How can I output the value object? I can't output the payload variable in a new $scope, because this data is dynamic.
Here is a simplified version of this on Plunker.
You should change the way you think about things when you work with asynchronous code. You no longer return values, instead you use Promise or callback patterns to invoke code when data becomes available.
In your case your factory can be:
.factory('dataService', function($http, $log, $q) {
return {
getTeacher: function(teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two').then(function(response) {
return response.data;
}, function() {
$log.error(msg, code);
})
}
};
});
And usage in controller:
dataService.getTeacher('Lanc').then(function(data) {
$scope.teacher = data;
});
Also $http.get already returns promise, so you don't have to create one more with $q.defer().
Demo: http://plnkr.co/edit/FNYmZg9NJR7GpjgKkWd6?p=preview
UPD
Here is another effort for combining lessons with teachers.
Demo: http://plnkr.co/edit/SXT5QaiZuiQGZe2Z6pb4?p=preview
//in your services file
return {
getTeacher: function (teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two')
})
//change the controller to this
dataService.getTeacher(teacherAbr).then(function(msg){
$scope.getdata=msg.data;
console.log("From server"+msg.data);
});

AngularJS promise and prevent redundant async calls

I have a wcf service method that gets some data and I call it using Microsoft Ajax library.
To share this data I create a dataService, and many controllers use this service.
I want every controller to get the same data after first call of getData is done, unless somebody need to refresh data and set forceRefresh to true.
My code fails because with the initialize of application 3 controler call dataService.getData and for all there start a new request. How can I make wait dataService.getData calls until the first one is finished and get same result for other subsequent ones..
angular.module('app', []).factory('dataService', function ($q) {
var data= [];
var getData= function (forceRefresh) {
console.log('getFolders called: ', reports.length);
var deferred = $q.defer();
if (forceRefresh || data.length < 1) {
WcfService.GetData(function(result) {
data= result;
deferred.resolve(data);
}, function(ex) { console.log(ex); });
} else {
deferred.resolve(reports);
}
return deferred.promise;
};
return {
getData: getData
};
});
One way would be to cache the promise, rather than the data, so it gets cached when it is created and not when the data arrives. After all, this sounds like your use case.
angular.module('app', []).factory('dataService', function ($q) {
var deferred = null;
var getData= function (forceRefresh) {
console.log('getFolders called: ', reports.length);
if(!forceRefresh && deferred) return deferred.promise;
deferred = $q.defer();
WcfService.GetData(
function(result) { deferred.resolve(data); }, // I'd promisify at a
function(ex){ deferred.reject(ex); } // higher level probably
);
return deferred.promise;
};
return {
getData: getData
};
});
how about setting a global flag in the $rootscope when a controller is querying for data, which can be checked before fetching the data by all the controllers, hence, avoiding redundant calls. The same flag can be put down when any of the controller has the promise fulfilled and data has been fetched, which can then be shared amongst all the controllers.
I found exactly what I search for
Promise queue for AngularJS services
http://inspectorit.com/tips-tricks/promise-queue-for-angularjs-services/

Resources