I would like to know if there is any impact of calling this.$scope.$digest(); after every AJAX download of script. I am using SignalR to get data from server. No sooner the data comes in than I want to have the data painted to the grid. While my functions in controller js execute within a winking time of the eye, the painting to the UI takes around 3 to 4 seconds which is unacceptable.
Angular Batarang says 6.8 ms and 1542 watchers.
How do I optimize the page?
There are two possible reasons for your issues. Either you are retrieving data very often, and trying to redraw it every time it is received. Or you are retrieving a lot of data and trying to update a control in your view that is very large. Here is how you solve both of these problems:
Data retrieval faster than update speed
For this you need to create a buffer between the retrieved data and the $scope data. Basically whenever you receive new data, you should push the changes to a data structure that isn't on scope. This way you can get data as fast as you want and it won't effect rendering. Then you need a heuristic for deciding when you want to redraw the data. This could be based on a timer, or something after data change. Once this condition is true, you copy the data changes over to your $scope object, which will update the view.
- receive data -> write to non scope buffer
- when some condition is met -> write buffer or buffer changes to $scope
Data retrieved is large, and view is large and complex
For this situation, your only option is to somehow simplify the view. With grids, this can be some sort of pagination or limiting constraint. There are plenty of angular grids out there that do these kinds of things, and I would just look for one that suits your situation better .
Related
I have been told it is 'bad practice' to return data from a Django view and use those returned items in Javascript that is loaded on the page.
For example: if I was writing an app that needed some extra data to load/display a javascript based graph, I was told it's wrong to pass that data directly into the javascript on the page from a template variable passed from the Django view.
My first thought:
Just get the data the graph needs in the django view and return it in a context variable to be used in the template. Then just reference that context variable directly in the javascript in the template.
It should load the data fine - but I was told that is the wrong way.
So how is it best achieved?
My second thought:
Spin up Django Rest Framework and create an endpoint where you pass any required data to and make an AJAX request when the page loads - then load the data and do the JS stuff needed.
This works, except for one thing, how do I get the variables required for the AJAX request into the AJAX request itself?
I'd have to get them either from the context (which is the 'wrong way') or get the parameters from the URL. Is there any easy way to parse the data out of the URL in JS? It seems like a pain in the neck just to get around not utilizing the view for the data needed and accessing those variables directly in the JS.
So, is it really 'bad practice' to pass data from the Django view and use it directly in the Javascript?
Are both methods acceptable?
What is the Django appropriate way to get data like that into the Javascript on a given page/template?
Passing data directly is not always the wrong way to go. JS is there so you can execute code when everything else is ready. So when they tell you it's the wrong way to pass data directly, it's because there is no point in making the page and data heavier than it should be before JS kicks in.
BUT it's okay to pass the essential data so your JS codes knows what it has to do. To make it more clear, let's look into your case:
You want to render a graph. And graphs are sometimes heavy to render and it can make the first render slow. And most of the time, graphs are not so useful without the extra context that your page provides. So in order to make your web page load faster, you let JS load your graph after your webpage has been rendered. And if you're going to wait, then there is no point in passing the extra data needed because it makes the page heavier and slows down the initial render and it takes time to parse and convert those data to JSON objects.
By removing the data and letting JS load them in the background, you make your page smaller and faster to render. So while a user is reading the context needed for your graph, JS will fetch the data needed and renders the graph. This will cause your web page to have a faster initial render.
So in general:
When to pass data directly:
When the initial data is necessary for JS to do what it has to (configs, defaults, etc).
When the time difference matters a lot and you can't wait too much for an extra request to complete the render.
When data is very small.
When not to pass data directly:
When rendering the extra data takes time anyway, so why not get the data latter too?
When the data size is big.
When you need to render something as fast as possible.
When there are some heavy processes needed for those data.
When JS can make your data size smaller (Decide what kind of data should be passed exactly using options that are only accessible by JS.)
I have used meteor publish and subscribe method to interact with client and server. Now according to my scenario I am using D3 js to generate a bar chart and as soon as the data is entered in mongo db collection I am using a client side function to generate a bar chart. My issue is that publish and subscribe is too slow to react. And even if I limit the number of documents returned by mongodb, the issue still persists. It is also inconsistent i.e. it will react under 1 second sometimes and other times it will take 4-5 second. Please guide me on what to do and what is wrong with my implementation.
Here is the server side code,
Test = new Mongo.Collection("test")
Meteor.publish('allowedData', function() {
return Test.find({});
})
and here is the client side code,
Test = new Mongo.Collection("test")
Meteor.subscribe('allowedData');
Meteor.setTimeout(function() {
Test.find().observe({
added: function(document){
//something
},
changed:function(){
//something
},
removed:function(){
//something
},
})
From your comments I see that you need a report chart which is reactive. Even though it is your requirement, it is too expensive to have a chart like this. In fact when you system grows bigger, say you have around 10000 documents for one single chart, this kind of chart will crash your server frequently.
To work around this problem, I have two suggestions:
Define a method that returns data for the chart. Set up a job/interval timer in client to call that method periodically. The interval value depends on your need, 10 seconds should be fine for charts. It is not completely reactive this way, you only get the newest data after an interval but it is still better than a slow and crash-frequent system. You could find good modules to manage job/timer here.
Use this Meteor package meteor-publish-join (disclaimer: I am the author), it is made to solve the kind of problem you have: the need to do reactive aggregations/joins on a big data set and still have a good overall performance
I created an app that stores, compares, filters and takes statistics out of a collection of records. I've done it so it works offline, as in some user cases the user might not have constant (or at all) access to internet.
My problem is that after I've included ~60 records, the app starts to behave really slow. For instance, I list a collection of simple objects from LocalStorage into a ng-model (Select list), and after those ~60 records are in, to open the Select box will be seriously slowed down.
What could the problem be? I'm thinking, either some function is sucking more resources than necessary, or LocalStorage is not intended for such uses?
I'm starting to get into PouchDB, would you say that migrating all to Pouch instead of LocalStorage would be a good move?
I can't paste the whole controller here as it's huge, but I've put an online version for testing. You can see it here.
For you not to have to create 60 records just to see the effect, you can download this CSV and import it in the app.
In order to import, the pass for Edit Mode is: admin
Let's see if someone has a tip for this one!
I see you are storing all your records inside a single LocalStorage value (with the key being recordspax). So yeah, that will get quite slow, because your app has to 1) JSON parse/stringify and 2) store/retrieve the entire list every time you read/write data to the database.
Basically you are reading your entire database in and out of disk for every operation. Since both LocalStorage and JSON stringify/parse happen synchronously on the main thread, it can block DOM rendering and will thus slow down your app.
PouchDB could be a help here, but you could also benefit from something simpler like LocalForage, or simply changing your DB design so that every record has its own key/value rather than storing everything into a single key with a single value.
(Both LocalForage and PouchDB use IndexedDB/WebSQL rather than LocalStorage, meaning that database operations are not synchronous and do not block the DOM. However, you still don't want to stuff everything into a single document and therefore read the entire DB in and out of disk. :))
Does anybody know how to use the JsonRest store in dojo witn an Observable weapper, like the one in dojo.store.Observable?
What do I need, server side, to implement the store and make it work as an Observable one? What about the client side?
The documentation says http://dojotoolkit.org/reference-guide/1.7/dojo/store/Observable.html
If you are using a server side store like the JsonRest store, you will need to provide a queryEngine in order for the update objects to be properly included or excluded from queries. If a queryEngine is not available, observe listener will be called with an undefined index.
But, I have no idea what they mean. I have never created a store myself, and am not 100% familiar with queryEngine (to be honest, I find it a little confusing). Why is queryEngine needed? What does the doc mean by "undefined index"? And how do you write a queryEngine for a JsonRest store? Shouldn't I use some kind of web socket for an observable REST store, since other users might change the data as well?
Confused!
I realize this quesiton is a bit old, but here's some info for future reference. Since this is a multi-part question, I'll break it down into separate pieces:
1) Server-side Implementation of JsonRest
There's a pretty decent write up on implementing the server side of JsonRest Store. It shows exactly what headers JsonRest will generate and what content will be included in the rest. It helps form a mental model of how the JsonRest api is converted into HTTP.
2) Query Engine
Earlier in the same page, how query() works client side is explained. Basically, the query() function needs to be able to receive an object literal (ex: {title:'Learning Dojo',categoryid:5}) and return the objects in the store that match those conditions. "In the store" meaning already loaded into memory on the client, not on the server.
Depending on what you're trying to do, there's probably no need to write your own queryEngine anyway -- just use the built-in SimpleQueryEngine if you're building your own custom store. The engine just needs to be handed an object literal and it adds the whole dojo query() api for you.
3) Observables
My understanding is that the Observables monitor client side changes in the collection of objects (ex: adding or removing a result) or even within a specific object (ex: post 5 has changed title). It does NOT monitor changes that happen server-side. It simply provides a mechanism to notify other aspects of the client-side app that data changed so that all aspects of the page stay synchronized.
There's a whole write up on using Observables under the headings 'Collection Data Binding' and 'Object Data Binding: dojo/Stateful'.
4) Concurrency
There's two things you'd want to do in order to keep your client side data synchronized with the server side data: a) polling for changes from other users on the server, b) using transactions to send data to the server.
a) To poll for changes to the data, you'd want to have your object store track the active query in a variable. Then, use setTimeout() or setInterval() to run the query in the background again every so often. Make sure that widgets or other aspects of your application use Observables to monitor changes in the query result set(s) they depend on. That way, changes on the server by other users would automatically be reflected throughout your application.
b) Use transactions to combine actions that must be combined. Then, make sure the server sends back HTTP 200 Status codes (meaning 'It Worked!'). If the transactions returns a HTTP status in the 400s, then it didn't work for some reason, and you need to requery the data because something changed on the backend. For example, the record you want to update was deleted, so you can't update it. There's a write up on transactions as well under the heading 'Transactional'
I'm working on a real-time JavaScript Application that requires all changes to a database are mirrored instantly in JavaScript and vise versa.
Right now, when changes are made in JavaScript, I make an ajax call to my API and make the corresponding changes to the DOM. On the server, the API handles the request and finishes up by sending a push using PubNub to the other current JavaScript users with the change that has been made. I also include a changeID that is sequential to JavaScript can resync the entire data set if it missed a push. Here is an example of that push:
{
"changeID":"2857693",
"type":"update",
"table":"users",
"where":{
"id":"32"
},
"set":{
"first_name":"Johnny",
"last_name":"Applesead"
}
}
When JavaScript gets this change, it updates the local storage and makes the corresponding DOM changes based on which table is being changed. Please keep in mind that my issue is not with updating the DOM, but with syncing the data from the database to JavaScript both quickly and seamlessly.
Going through this, I can't help but think that this is a terribly complicated solution to something that should be reasonably simple. Am I missing a Gotcha? How would you sync multiple JavaScript Clients with a MySQL Database seamlessly?
Just to update the question a few months later - I ended up sticking with this method and it works quite well.
I know this is an old question, but I've spent a lot of time working on this exact same problem although for a completely different context. I am creating a Phonegap App and it has to work offline and sync at a later point.
The big revelation for me is that what I really need is a version control between the browser and the server so that's what I made. stores data in sets and keys within those sets and versions all of those individually. When things go wrong there is a conflict resolution callback that you can use to resolve it.
I just put the project on GitHub, it's URL is https://github.com/forbesmyester/SyncIt