So I have an endpoint which returns the contents of many entities in parallel.
I have a shared service which calls this endpoint and puts them into a shared $cacheFactory.
When GET /base_entity/<id>/all route is hit first, then GET /entity/<id> should return the cached copy.
What's best-practice in telling the GET /entity/<id> service to not perform an HTTP get until GET /base_entity/<id>/all has had a chance to complete?
$broadcast/$emit approach seems odd. I suppose I could use that shared $cacheFactory with cache.put('START /all for ID:' +, id) and cache.put('FIN /all for ID:' +, id), but not sure if that's a strange way of solving the problem.
Ended up creating a new view and controller. The controller's constructor calls GET /base_entity/<id>/all and caches it then does a $state.go passing along current $stateParams. Concurrently the view shows a shiny graphic loading directive.
Now when /entity/<id> state is transitioned to, the service first checks ALL cache; updates its cache accordingly; then checks cache and returns that in a $q promise, or hits $http otherwise.
Related
I have an app that shows statuses for internal processes. It also has a separate view that allows you to set up new records. To set up a new record, you fill out a form, and upon submit a call is made to my nodejs server that:
inserts the record into a table
kicks off a stored procedure
routes you back to the status page
The issue here, is that the page hangs while this happens, as sometimes the stored procedure takes a minute or two to run. So you wait for a couple minutes, and then are routed back to the status page.
Now, I don't actually care to see any exit code for this stored proc on the front end, as you will see the status of it on the status page. I'm wondering if there's a way for me to kick this process off, but not have the front end care about the return.
I've tried adding in the $location.path() before the $http call to the server, but then the $http call never happens.
Any ideas?
Thanks!
You can wrap the stored procedure call in a promise. The browser will make the call and continue on without waiting for it to complete and you can react appropriately in the resolve or reject functions. You can use angular's $q service:
insertRecord();
$q(function() {
storedProcCall();
});
redirect();
I'm trying to find a generic solution to commit/rollback a model alongside ng-resource.
When to commit/save model:
Successful http write methods (PUT, POST, PATCH).
When to rollback/reset model:
Failing http write methods.
User deciding to cancel their local changes (before PUT).
I've found pieces of this solution scattered, but no comprehensive strategy.
My initial strategy was to make use of the default ng-resource cache. Controller starts with GETting an item. If a subsequent PUT/POST/PATCH failed (caught either in the controller's promise, or in the $resource.<write_method>'s interceptor.responseError, re-run the GET that first got the object, and replace my model with that, as on initial load. However, this doesn't help if there's a successful PUT, followed by a failed one, because I'd be replacing my model with a stale object. The same problem occurs when a user tries to cancel their form changes before submitting... the last successful GET may be stale.
I've got a model with ~10 properties, and multiple <form>s (for html/design's sake) that all interact with this one object that gets PUT upon any of the forms being submitted:
{'location_id': 1234,
'address': {
'line1': '123 Fake St'}
...
},
'phone': '707-123-4567',
...
}
Models already have nice rollback features, but getting ng-resource to touch them seems tricky, and I really want to reset the entire object/model. Using a custom cache alongside my $resource instance seems like a decent way to go, but is equally tricky to give user-interaction a way to rollback. Another idea was to store a separate object when loading into scope: $scope.location = respData; $scope._location = angular.copy(respData); that I could load from when wanting to roll back, by way of $scope.location = $scope._location;, but I really don't want to clutter my controllers site-wide with these shadow objects/functions (DRY).
I'm new to AngularJS and I am currently building a webapp using a Django/Tastypie API. This webapp works with posts and an API call (GET) looks like :
{
title: "Bootstrap: wider input field - Stack Overflow",
link: "http://stackoverflow.com/questions/978...",
author: "/v1/users/1/",
resource_uri: "/v1/posts/18/",
}
To request these objects, I created an angular's service which embed resources declared like the following one :
Post: $resource(ConfigurationService.API_URL_RESOURCE + '/v1/posts/:id/')
Everything works like a charm but I would like to solve two problems :
How to properly replace the author field by its value ? In other word, how the request as automatically as possible every reference field ?
How to cache this value to avoid several calls on the same endpoint ?
Again, I'm new to angularJS and I might missed something in my comprehension of the $resource object.
Thanks,
Maxime.
With regard to question one, I know of no trivial, out-of-the-box solution. I suppose you could use custom response transformers to launch subsidiary $resource requests, attaching promises from those requests as properties of the response object (in place of the URLs). Recent versions of the $resource factory allow you to specify such a transformer for $resource instances. You would delegate to the global default response transformer ($httpProvider.defaults.transformResponse) to get your actual JSON, then substitute properties and launch subsidiary requests from there. And remember, when delegating this way, to pass along the first TWO, not ONE, parameters your own response transformer receives when it is called, even though the documentation mentions only one (I learned this the hard way).
There's no way to know when every last promise has been fulfilled, but I presume you won't have any code that will depend on this knowledge (as it is common for your UI to just be bound to bits and pieces of the model object, itself a promise, returned by the original HTTP request).
As for question two, I'm not sure whether you're referring to your main object (in which case $scope should suffice as a means of retaining a reference) or these subsidiary objects that you propose to download as a means of assembling an aggregate on the client side. Presuming the latter, I guess you could do something like maintaining a hash relating URLs to objects in your $scope, say, and have the success functions on your subsidiary $resource requests update this dictionary. Then you could make the response transformer I described above check the hash first to see if it's already got the resource instance desired, getting the $resource from the back end only when such a local copy is absent.
This is all a bunch of work (and round trips) to assemble resources on the client side when it might be much easier just to assemble your aggregate in your application layer and serve it up pre-cooked. REST sets no expectations for data normalization.
I have an app that uses CakeSession for saving different user data. Now I want to write some default values using CakeSession::write() and have them available for all views (also for cached views). So the check/write should be done on every request before the view is rendered.
But where to put the code to match these requirements? Until now, I tried the following positions to use CakeSession::write() but without success:
Config/bootstrap.php -> CakeSession is not defined yet
AppController::__construct() -> CakeSession is not defined yet
AppController::beforeFilter() -> will not be called for cached views
Nowhere will cached views create sessions. A cached view does not initialise a request at all
docs
It should be noted that once an action is cached, the controller method for the
action will not be called. When a cache file is created, the request object,
and view variables are serialized with PHP’s serialize().
My program fills an array with data from a facebook page feed but every time i go from one tab to another it wants to reload this data, is there any way i can cache this array so that it will not reload the information unless its changed?
This is exactly why your Views should not contain Service logic. Instead, your View should dispatch an event asking for the service call and your Controller (you do have one, right?) should catch that event and decide whether to act on it or not.
How do you know the data hasn't changed without reloading it?
Maybe what you need is to store the timestamp of the last service call, than measure the amount of time before executing the service call again.
Perhaps with a 5-minute timeout, if the user continuously changes tabs within 5-minutes from the last service call, the array persists previously loaded data.
After 5-minutes, if the user changes back to that tab the service call can fire, load data, than update the timestamp to prevent loading.