How can I save JSON data from an API service to cache? - angularjs

I call the API service from the backend side. I want to save the JSON return data to the cache. What should I do? Is my format wrong?
The snippet code here:
// var localData = [];
var service = {
search: function(requestId) {
return $http.get('/api/mace/getRequest', {
params: {
id: requestId
},
cache:true
});
},
return service

I can't see that there's something wrong with your code. You did correctly set the cache variable to true in the http-call as described in the documentation from AngularJS.
$http.get(url, {
cache: true
}
You should get your JSON by calling your service function and waiting for the promise:
yourService.search(yourRequestId).then(function(response) {
console.log('result', response.data);
});

Related

Angular return promise from httpBackend.when()

How do you return a promise from httpBackend.when()? I wanted to load some canned data stored in a .json file and return that from httpBackend.whenGET(). When I try to return the promise from http.get('mydata.json') the response is returned to the failure callback of the factory.
function getAvailablePackagesComplete(response) {
return response.data;
}
function getAvailablePackagesFailed(error) { // {error = Object {data: undefined, status: 0, config: Object, statusText: ""}
$log.error(error.data.description);
return false;
}
function getAvailablePackages() {
return $http.get('/1.0/get-available-packages')
.then(getAvailablePackagesComplete)
.catch(getAvailablePackagesFailed)
}
var data = {"package": "test", "version": "1"}
$httpBackend.whenGET('/1.0/get-available-packages').respond(function(method, url, data) {
// return [200,data, {}] // this works
return $http.get('app/home/fixtures/mydata.json'); // contains {"package: "test", "version": "1"}
}); //this doesn't work
As it is currently, $httpBackend (from ngMockE2E) does not support promises within its .respond - See AngularJS GitHub Issue #11245. As $httpBackend should be used to avoid making real HTTP requests, but you could let some requests pass through.
From AngularJS Docs:
This implementation can be used to respond with static or dynamic responses via the when api and its shortcuts (whenGET, whenPOST, etc) and optionally pass through requests to the real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch templates from a webserver).
To work around what you're trying to do though, you could try to have getAvailablePackages() return the HTTP GET for your json file path and defining an $httpBackend.whenGET('pathTo.json').passThrough();
I was hitting the same issue and my use case was building a mock of my entire API in JS so that other people could work off line and develop the UI.
To achieve that I have developed a plugin called angular-mocks-async which decorates the httpBackend and adds the .whenAsync( ) APi to it. Than you can easily mock responses and return promises like so:
var app = ng.module( 'mockApp', [
'ngMockE2E',
'ngMockE2EAsync'
]);
app.run( [ '$httpBackend', '$q', function( $httpBackend, $q ) {
$httpBackend.whenAsync(
'GET',
new RegExp( 'http://api.example.com/user/.+$' )
).respond( function( method, url, data, config ) {
var re = /.*\/user\/(\w+)/;
var userId = parseInt(url.replace(re, '$1'), 10);
var response = $q.defer();
setTimeout( function() {
var data = {
userId: userId
};
response.resolve( [ 200, "mock response", data ] );
}, 1000 );
return response.promise;
});
}]);
You can return promises from http interceptors. Here is an example of delaying an HTTP call for 1 second. You can add this in your app.config(....)
$httpProvider.interceptors.push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 1000);
return defer.promise;
}
};
});

unable to display the http get response from the factory in controller in Angularjs application

In my service I making http get request as shown below:
.factory('InvoicesGeneralService', function ($http) {
return {
getAgreementsByCourierId: function (courierId) {
console.log("Courier in Services" + courierId);
return $http.get('/api/agreements/byCourierId', {params: {courierId: courierId}}).then(function (response) {
return response;
});
}
};
});
And in browser console I am seeing the following response :
[
{
"id":3,
"number":"AGR53786",
"ediNumber":"EDI7365",
"startDate":"2012-09-02",
"endDate":"2018-07-01",
"courier":{
"id":2,
"name":"FedEx",
"url":"www.fedex.com",
"isActive":true,
"isParcel":true
},
"client":{
"id":4,
"code":"KJGTR",
"name":"Hearty",
"isActive":true,
"engageDate":"2011-07-07",
"isSendRemittance":true,
"upsUserName":"Tkd",
"upsPassword":"kuu",
"isEligibleForTracking":true,
"isEligibleForAuditing":true,
"status":5
}
}
]
And in my controller I am assigning it to result List :
$scope.resultList = InvoicesGeneralService.getAgreementsByCourierId(selCourierId);
But my resultList is always appearing as Empty. Can any one help me, why it is happening?
When I am trying to display resultList as shown below, it always shows empty object, {}. It supposed to display the response json array from the service but it is showing empty object.
<pre class="code"> {{resultList | json}}</pre>
$http returns a promise. Anything consuming that data needs to handle it like a promise too.
InvoicesGeneralService.getAgreementsByCourierId(selCourierId).then(function(data) {
$scope.resultList = data;
});
Also, your factory's then function is not doing anything at the moment. You should return the response's data from it.
return $http.get('/api/agreements/byCourierId', {params: {courierId: courierId}}).then(function (response) {
return response.data;
});

Issue with callback on polling Angular API call

I have a continuously polling API request. I'm using the angular-poller service to assist with this.
var gamesPoller = poller.get(apiURL, {
method: 'GET',
delay: 6000,
// smart: true,
argumentsArray: [
{
params: {
token: token
}
}
]
});
gamesPoller.promise.then(function(response) {
$log.debug('promise resolved, data assigned');
$scope.gameData = response.data.List;
$log.debug($scope.gameData);
}, function(response) {
$log.warn('Error in $http - getGames in controller...');
}, callback);
In the network panel, I see the request made, resolving with a 200, and the response data. And it is making the request every 6 seconds like it should. However, the data isn't getting assigned to the $scope var. And nothing in the promise is being assigned/run.
Looks like the view code needs to be set in the call
gamesPoller.promise.then(null, null, function(response) {
$log.debug(response.data);
$cookies.put('Token', response.data.Token);
$log.debug('getGames: ' + response.data.List);
return $scope.gameData = response.data.List;
console.log($scope.gameData);
}, function(response) {
$log.warn('Error in $http - getGames in controller...');
});

Getting a single result with angularjs factory in MEAN stack

I'm trying to grab a single result from my expressjs api from within my AngularJS factory.
The factory looks like this and grabs all posts from my api(written in expressjs and getting data from mongodb), which is working fine:
angular.module('bonsaiService', ['ngResource']).
factory('bonsaiService', function($q,$resource) {
var bonsaiResource = $resource('http://localhost:8888/api/bonsais/:bonsaiId',{},{
get:{
method: 'GET',
params:{bonsaiId:''},
isArray: true
}
});
return {
get:function(){
var q = $q.defer();
bonsaiResource.get({
},
function(resp){
q.resolve(resp);
},function(httpResponse){
q.reject(httpResponse);
});
return q.promise;
}
//find by id
};
});
What i've tried so far is adding :bonsaiId after the $resource url and adding params for that id like this: params:{bonsaiId: ''}.
The server part (expressJS) look like this:
router.route('/bonsais/:bonsaiId')
.get(function(req,res){
Bonsai.findOne(req.params.bonsaiId,function(err,bonsai){
if(err)
res.send(err);
res.json(bonsai)
})
})
When I call a local url (with and existing _id from mongodb) it works fine and returns my data in json :
http://localhost:8888/api/bonsais/536be2e2ae54668818000001
Now in the controller im trying to get this data in my scope, which is not working.
bonsaiService.get({bonsaiId:$routeParams.bonsaiId}).then(
function(data){
$scope.trees = data;
console.log(data);
});
How do I make this work?
You could use a more simple approach here.
The query method for $resource already defines a GET on an array, which is QUERY.
Why not write your service this way :
.factory('bonsaiService', ['$resource',
function($resource) {
return $resource('http://localhost:8888/api/bonsais/:bonsaiId', {
bonsaiId: '#bonsaiId'
});
}
])
And in your controller, it would work like this :
bonsaiService.query({
bonsaiId: $routeParams.bonsaiId
}, function success() {
//Your code
}, function err() {
//Your code
});
Don't forget to inject the service in the controller or the app file, if it's not done already.

Passing 'filter' parameter to angular resource (DreamFactory rest api)

I am having an issue with query parameters from my AngularJS app
I am reading documents from MongoDB using DreamFactory rest api like this:
.service('Servant', ['$resource', function($resource) {
// define and return $resource
return $resource('https://mydsp.cloud.dreamfactory.com:443/rest/mongodb/tablename',
{
// set params to bind too
app_name: 'myapp',
fields: '#fields',
limit: '#limit',
offset: '#offset',
filter: '#filter'
},
{
// set update method to 'PUT'
update: {
method: 'PUT'
}
}
)
}]);
This all works great when I set filter like "parameter=value" but I failed to find a way of passing more complicated filter param in JSON format as described here, using $in parameter etc. Does anyone know the right syntax for this?
EDIT:
just tried something like
filter = angular.toJson("{'parameter':{$in:['value1','value2']}}")
with no success...
First...drop the port from your service url. 'https' for dreamfactory specifies port 443. No need for you to do it explicitly. Second...You should be able to pass a SQL style filter as a string in your params. When you set up your $resource the way you have you should be able to pass a params object to it. No need to stringify or toJson anything. DreamFactory should handle it. For example...
Here is your service:
.service('Servant', ['$resource', function($resource) {
return $resource('https://mydsp.cloud.dreamfactory.com/rest/mongodb/tablename',
{
app_name: 'myapp',
fields: '#fields',
limit: '#limit',
offset: '#offset',
filter: '#filter'
},
{
update: {
method: 'PUT'
}
}
}]);
Calling that service with a params object:
// the 'parameter' value in our filter string should relate to a field and/or property
scope.paramsObj = {
fields: '*',
limit: 10,
offset: 0,
filter: 'parameter in (5,15)'
}
// call service and handle promise returned by $resource
Servant.get(scope.paramsObj).then(
function(result) {
// handle success
// like assign to a var or something
// here we just log it
console.log(result)
},
function(error) {
// handle error
// probably should throw an error here
// but we just log it here
console.log(error);
});
EDIT
Ok. So...it should work with SQL style filter strings. An issue has been logged with DreamFactory. In the mean time you can create a custom $resource action to handle the filters and tunnel your GET request through a POST. Easier then it sounds. See code below.
Here is the service with custom action
.service('Servant', ['DSP_URL', '$resource', function (DSP_URL, $resource) {
return $resource(DSP_URL + '/rest/mongohq/Colors', {
// params to bind to
app_name: YOUR_APP_NAME_HERE,
fields: '#fields',
limit: '#limit',
offset: '#offset'
}, {
// custom $resource action
'getFiltered': {
// set our method to post because we have to post
// our filter object
method: 'POST',
// We can transform the data before the post.
// In the circumstance we do need to stringify
// So that's what we do here.
transformRequest: function (data) {
return JSON.stringify(data);
}
}
})
}]);
Here is the controller:
.controller('MongoCtrl', ['$scope', 'Servant', function ($scope, Servant) {
// Create a params object
// This requests all fields.
// And we explicitly set the method to
// GET. We are tunneling a GET request
// through our POST because our filter
// needs to be posted but we really want a GET.
$scope.params = {
fields: '*',
method: 'GET'
};
// Call our Service with our custom $resource action
Servant.getFiltered(
// Send our params
$scope.params,
// Send our filter as post data
{
"filter": {
"color": {
"$in": ["blue", "white"]
}
}
},
// handle success
function (data) {
console.log(data)
},
// handle error
function (error) {
console.log(error)
})
}])
I guess you should stringify your filter data:
resource.update( {
filter: JSON.stringify( {qty:{$in:[5,15]}} )
});
Or in this way:
resource.get({id:123}, function() {
resource.filter = JSON.stringify( {qty:{$in:[5,15]}} );
resource.$update();
});

Resources