AngularJS: Declaring unique variable inside interceptor - angularjs

I have a need to have a variable that is unique per request inside my http interceptor. So when the request comes in I want to set this variable to some value and read that value on the response. The issue is that the interceptors are shared so every time a new request comes in my variable will just be overridden.
angular.module('app').factory('httpInterceptor', ['$q',
function($q) {
var myInstanceVar = "";
return {
request: function (config) {
myInstanceVar = Math.random();
return config;
},
response: function (response) {
console.log(myInstanceVar);
return response || $q.when(response);
}
}
}
]);
So in this example, I would want myInstanceVar to be unique when I output the value in response but instead it just outputs the value that was generated the last request. So if I have 3 requests the output would be 3,3,3 instead of like 5,9,3 since the last request set it to 3.
I know I could probably just append the value to the request body and have the server return it back but I want to avoid that if possible.
I am using AngularJS 1.6.4 if that matters.

You can store the variable in the config, and get it back in response.config.

Related

How to contact a non-standard API using Angular ngResource

The API I am using requires a non-standard where clause if I try to search for a particular non-id field. The endpoint I need is:
http://127.0.0.1:4001/api/testusers/findOne?userName=Anton
So this will find me the first record in the testusers table whose column (userName) = 'Anton'.
My standard service is:
angular.
module('shared.testUser').
factory('TestUser', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/:id', {id:'#id'},//parameters
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
and my calling function is:
self.checkUsersEntryDirection = function(){ //NOT WORKING
self.testuser = TestUser.get({ username: 'anton' }, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
Clearly this doesn't work and I can't use the standard get approach. Can anyone think how this can be achieved?
You could create a secondary factory TestUserByName, and make the following changes:
angular.
module('shared.testUser').
factory('TestUserByName', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/findOne?userName:username', null,
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
Call the get action method with two parameters:
var params = {id: "findOne", username: "anton"};
self.checkUsersEntryDirection = function(){
self.testuser = TestUser.get(params, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
The id parameter will override the default and username parameter will be added as a query string.
From the DOCS:
Each key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.
Given a template /path/:verb and parameter {verb:'greet', salutation:'Hello'} results in URL /path/greet?salutation=Hello.
--AngularJS ngResource $resource Service API Reference

How to get a where clause using ngResource in angularJS

I have a simple service given here and I want to get a record(s) using a where clause, i.e. the endpoint would http://127.0.0.1:4001/api/testusers?userName=anton
The service is:
angular.
module('shared.testUser').
factory('TestUser', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/:id', {id:'#id'},//parameters
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
And the controller code I have tried is:
self.checkUsersEntryDirection = function(){ //NOT WORKING
self.testuser = TestUser.get({ username: 'anton' }, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
The error I get is
Error in resource configuration for action get. Expected response to contain an object but got an array (Request: GET http://127.0.0.1:4001/api/testusers)
Notice how it didn't add on the where clause. I thought that any extra properties provided would be assigned as where clause items??
thanks

Service which returns multiple promises based on data from single HTTP request

I wish to implement a service which has the following features:
Performs a HTTP request to a given resource only once.
Provides two exported functions, each of which return a promise, where the promise is resolved based on data from the one-time HTTP call.
The two functions shall exist to provide different representations of the fetched data.
The outline of my service so far is as follows:
angular.module('someApp')
.service('someService', function ($http) {
var httpPromise = $http.get('/some/endpoint/').then(
function(response) {
// HTTP response data is processed
});
this.getSomePromise = function() {
// Return a promise which is resolved using one representation of HTTP response
}
this.getAnotherPromise = function() {
// Return a promise which is resolved using another representation of HTTP response
}
});
If there was only the need for one 'getter' function then clearly I could simply have returned the httpPromise.
What is the appropriate way to implement the interface as shown? Is it possible for two or more consumers to call .then() on the same promise, in which case I could merely return httpPromise.then(function(){...modify data...}) from both functions? Or, in this scenario would it be necessary to create a new promise (using $q.defer()) and resolve it somehow based on a cache object which holds the HTTP response?
You can simply create two promises, using chaining, on the http promise:
var httpPromise = $http.get('/some/endpoint/');
var firstPromise = httpPromise.then(function(response) {
return firstTransformation(response.data);
});
var secondPromise = httpPromise.then(function(response) {
return secondTransformation(response.data);
});
this.getSomePromise = function() {
return firstPromise;
}
this.getAnotherPromise = function() {
return secondPromise;
}

Return data from service in time

I have a factory, which is returning a ngResource
.factory('web'... {
return $resource(URL, null, {
create: {method: 'POST'}
}
}
then I have a service which needs to get data from the above factory only if a URL param changed, or if the variable where I store the response is empty.
var query = Web.get(param);
query.$promise.then(function(res) {
variable = res;
}
return variable
Then I call the above service, to get some data, if variable is empty, make a request, else return variable.
The problem is that because of the request I don't get any data, how can I fix this? Also I would like to get the value of response not a promise.
UPDATE:
Why I don't need a promise.
At one point I will have all the data that I need, so I don't have to make request on Web. So from an array of objects, the user will be able to select one object, and then the variable from above will have the value of the selected object.
Now my function will return an object instead of a promise, I guess I can check the return type, but I hoped there is another way.
At the time your function returns the promise hasn't resolved so you always get undefined returned.
You should return the promise to your calling function and let that wait for the promise to resolve or handle any errors.
var query = Web.get(param);
return query.$promise;
The problem is that because of the request I don't get any data, how can I fix this? Also I would like to get the value of response not a promise.
Unless I'm very much mistaken, you can't.
UPDATE based on updated question
You still need a promise to do what you want. Its not too difficult to difficult to wrap it all up.
function getData(param)
{
va deferred = $q.defer();
if (variable){
// Already got what we need
deferred.resolve(variable);
}
else
{
// Lookup the data
var query = Web.get(param);
query.$promise.then(function(res) {
variable = res; // Save for later
deferred.resolve(variable);
},
function(err){
deffered.reject(err);
});
}
return deferred.promise;
}

Implementing Interceptor in AngularJS

Looking at this AuthInterceptor from this helpful answer, how are the request and response key's used in the returned JSON object?
Also, what's the meaning of return config || $q.when(config)? I understand that the second part is returned if config is null or undefined, but what does $q.when(config) mean in this code?
myApp.factory('AuthInterceptor', function ($window, $q) {
return {
'request': function(config) {
config.headers = config.headers || {};
if ($window.sessionStorage.getItem('token')) {
config.headers.Authorization = $window.sessionStorage.getItem('token');
}
return config || $q.when(config);
},
'response': function(response) {
if(response.status === 401) {
$location('/login');
}
return response || $q.when(response);
}
};
});
I typed out the above linked answer. It worked for me, but I don't understand how it's used.
When registering an $http interceptor, you should essentially pass an object with the following (optional) keys: request, requestError, response, responseError.
For more info on when each interceptor function is called, take a look at this answer.
$q.when() turns any JS object into a promise (that resolved immediatelly with the passed in object as each resolved value). But, frankly (although I've seen it a lot) I don't understand why one would need to return config || $q.when(config), instead of just config.
request and response are simple used as intermediaries. In other words, the request function is run prior to a request (after requesting), and the response function is run prior to handling a request result.
$q.when() ensures that the return value is able to be handled as a promise. Essentially it wraps the value in a promise, so that functions like returnedValue.then() work.
See: https://docs.angularjs.org/api/ng/service/$q
Kevin asked why you would want to use $q.when(). This is to ensure that any outside function that consumes this one receives a promise, if it is expecting one. For example, imagine the situation where you call a function expecting a promise:
someThirdPartyFunc(someArg).then(function(result){
// do somethign with result
});
If you ran this and someThirdPartyFunc returned a simple value (say 100), then this would obviously fail. If the implementor wrapped the return value in $q.when(100), then the function call above would be valid, and result would contain the value 100.

Resources