1

** ANGULAR 1.X ** Hello everyone! I need help with making this $http.get function asynchronous, as you can see from the code, my current temp solution is to setInterval the displayData scope. Which obviously is not an efficient solution, because it takes up too much CPU, too much of the users data and can cause some flickering on the UI. I want the array to be updated when the database is updated. Please do not recommend I switch to other frameworks. thank you

$scope.displayData = function() {
    $http.get("read.php").success(function(data) {
        $scope.links = data;
    });
}
setInterval(function(){$scope.displayData();}, 500);

This is my PHP ("read.php")

  <?php
  include("../php/connect.php");
  session_start();
  $output = array();
  $team_id = $_SESSION['team_id'];
  $sql  = "SELECT record_id, user_id, link, note, timestamp FROM             
  link_bank WHERE team_id = '$team_id' AND status = 'valid'";
  $result = mysqli_query($connect, $sql);
  if (mysqli_num_rows($result) > 0) {
        while ($row = mysqli_fetch_array($result)) {
        $output[] = $row;        
  }
  echo json_encode($output);
  }
  ?> 
georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Consider adopting a push notification strategy using sockets. See [How to integrate nodeJS + Socket.IO and PHP?](https://stackoverflow.com/questions/17209717/how-to-integrate-nodejs-socket-io-and-php) See also [Real time chat, message handling - Socket.io, PHP, MySQL, Apache](https://stackoverflow.com/questions/45348866/real-time-chat-message-handling-socket-io-php-mysql-apache). – georgeawg Dec 01 '17 at 16:12

2 Answers2

1

$http.get is already asynchronous! An asynchronous function is just any function that finishes running at some unknown time in the future.

What you are really trying to do is called long polling. This is where you periodically send a request to your server to get the latest data, and there are several reasons why it's not a good idea (including the flickering and high CPU usage you spoke of).

I know you said you don't want anyone to suggest other frameworks, but trying to write your own framework that will notify the client when the database is updated is a monumental task. There is no short snippet of code we can give you that will give you that functionality from just PHP and Javascript.

However, you could try to roll your own code using WebSockets. That is the most straightforward, non-framework way to have server-to-client communication in the way you are suggesting.

Pop-A-Stash
  • 6,572
  • 5
  • 28
  • 54
  • What i mean by other frameworks, is to suggest i scrap angular 1.x and/or php and start all over with new frameworks. I don't mind adding to what I already have. – Abdul Amoud Nov 30 '17 at 20:32
  • Ok, great. Take a look at Ratchet (http://socketo.me/) for PHP. That should get you started. – Pop-A-Stash Nov 30 '17 at 20:35
  • 1
    @AbdulAmoud PHP is a language, JS is a language, Angular is a framework just to clarify. Also the way you are polling is very inefficient especially if the network latency ends up being close to your 500ms interval. The other issue is you're using $http which automatically triggers a digest and you're replacing the array every single time regardless of if something changed or not. If you send along the last changed time and in the response indicate if the data has changed you'd have far less "flickering". Use the chrome profiling and timeline tools. – shaunhusain Nov 30 '17 at 20:38
  • I doubt if getting the data in a more efficient way is going to matter too much it seems like mostly problems with the way the client side code is written currently it just needs to be optimized. – shaunhusain Nov 30 '17 at 20:38
  • I was looking at socket.io website, and it seems like it only focuses on node.js. – Abdul Amoud Nov 30 '17 at 20:41
  • If you can show your site live temporarily somewhere so we can take a look I can give you my .02 from profiling but without hands on hard to say exactly where things are getting really slow (could be lack of virtual scrolling and too many dom elements/watchers or something else) If not could recreate roughly the client side code using flickr api or some other public one. – shaunhusain Nov 30 '17 at 20:41
  • OK yah I agree with this answer now you are trying to send far too much data far too quickly most of those network requests are taking more than 500ms and are happening in a constant stream that's going to be really inefficient both on the network and on the client... how real time does this data actually need to be? are we talking high speed trading or "near real time chat" Seeing a flood of requests with nothing in the response body but still taking some time to process server side. – shaunhusain Nov 30 '17 at 20:49
  • I'm most likely not going to change much to this project, I've built a chat system based on the solution i have from the question. But I want it to be more efficient (This is all an exercise for me). So yes, the calls need to be as frequent as 500ms or at least 1000ms. I don't mind tossing the work to the server, i just don't want the client side to suffer. The reason why I want an easy solution is not because I'm lazy, I am dealing with a host that doesn't not give me root access, so I need a solution that works with what I have. – Abdul Amoud Nov 30 '17 at 20:57
0

Some details from checking the debug tools, there are tons of network requests that are taking a long time and not returning any new data.

enter image description here

Using the timeline recording to get some details on the client side processing.

enter image description here

enter image description here

The client side isn't suffering that much in the view I'm seeing but without data it's hard to really assess.

You can see by taking a timeline then zooming in on a section of the recorded data what actual functions were called and how long they took. There are also nice extensions for checking $watchers in angular

https://chrome.google.com/webstore/detail/angular-watchers/nlmjblobloedpmkmmckeehnbfalnjnjk?hl=en

You can use {{::bindOnce}} syntax to reduce your watchers if bindings are only ever updated one time (useful in ng-repeats many times). This helps to reduce digest time since less watchers need to be checked for changes. If you have a very long list of elements (1000s) then using some sort of virtual scroller or paging UI-component is helpful to avoid making 1000*elements per row elements in the DOM.

On the server side you can use the xdebug plugin/module for collecting profiling data from the server side and can use kcachegrind to evaluate that data to look for where the server is spending the most time but could also utilize some sort of server side caching and smarter logic there to avoid hitting the database constantly if nothing has changed (perhaps look into using Redis or look into memcached for speeding those server side things up or see if it's just network latency).

Changing languages or frameworks without actually profiling to get data on what exactly is slow isn't a great move IMO will just be jumping around between whatever is the new hotness without an understanding of why or if it matters.

Example below of a relatively fast response from a PHP script. It does basically nothing but spit out a hard coded JSON response, using Redis or memcached there wouldn't be much extra overhead to get back a response especially an empty one.

enter image description here

shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • Thank you for the detailed answer, but I really was hoping for a change in how the service is carried out. – Abdul Amoud Nov 30 '17 at 21:16
  • @AbdulAmoud the answer is it depends and you need to gather more data to identify what is slow really. I left some suggestions on common problems/solutions but there is no silver bullet. – shaunhusain Nov 30 '17 at 21:17
  • Nothing is really slow, other than the occasional flickering. I haven't gotten any bad reviews. One thing though, if you make an entry and try to select it, so you could copy it, the select disappears before the user gets the chance to copy and that happens because the entry is basically disappearing and replacing itself. This is actually good for now, but I'm aiming to create apps that will potentially, be used by thousands of people, and this will certainly not do. – Abdul Amoud Nov 30 '17 at 21:24
  • 500ms to get an empty response is pretty slow my server giving a fairly direct response takes about 50ms if you are expecting things to happen in a given window of time then you need to think of slow in terms of that window. For script execution on the client side more than 16ms of execution per frame means frames are longer than 1/60 a second which means you aren't getting 60fps, time is relative. Regarding the "flickering" if you weren't replacing the elements when the data doesn't change you wouldn't have this issue. – shaunhusain Nov 30 '17 at 21:53
  • Also regarding "flicker" if you can reproduce the issue you are seeing in a jsfiddle or plnkr or somewhere it can be poked at then I can try to address the specific issue but again no silver bullet it just depends on what you're doing – shaunhusain Nov 30 '17 at 21:55
  • " if you weren't replacing the elements when the data doesn't change you wouldn't have this issue. " Thats exactly what I'm trying to avoid – Abdul Amoud Nov 30 '17 at 22:09
  • @AbdulAmoud well right that can/needs to be handled a few places I think. On the server side would be good to check for new data in the DB or against some faster cache to see if the DB has changed before even hitting the DB so it can give fast responses. On the client side can get the response and if it indicates there was no change can avoid updating the collection in question. – shaunhusain Nov 30 '17 at 22:10
  • Having up to date data, without looping the request. – Abdul Amoud Nov 30 '17 at 22:11
  • If you don't update the object the view is bound to then the view won't update I guess is the long story short :) How you get the data isn't really so important but calls to $http.get do trigger a call to $digest which makes any watchers fire so if you can reduce those it'd be great too (you can also do ajax calls outside of angular context by circumventing $http but then need to manually trigger $digest when the model changes) – shaunhusain Nov 30 '17 at 22:13