Как эффективно опросить базу данных mySQL с помощью $http.get

** ANGULAR 1.X ** Всем привет! Мне нужна помощь в том, чтобы сделать эту функцию $http.get асинхронной, как вы можете видеть из кода, мое текущее временное решение — установить интервал области отображения данных. Очевидно, что это неэффективное решение, потому что оно занимает слишком много ресурсов ЦП, слишком много пользовательских данных и может вызвать некоторое мерцание в пользовательском интерфейсе. Я хочу, чтобы массив обновлялся при обновлении базы данных. Пожалуйста, не рекомендуйте мне переходить на другие фреймворки. Спасибо

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

Это мой 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);
  }
  ?> 

person Abdul Amoud    schedule 30.11.2017    source источник
comment
Рассмотрите возможность использования стратегии push-уведомлений с использованием сокетов. См. Как интегрировать nodeJS + Socket.IO и PHP? См. также Чат в реальном времени, обработка сообщений - Socket.io , PHP, MySQL, Apache.   -  person georgeawg    schedule 01.12.2017


Ответы (2)


Некоторые подробности из проверки инструментов отладки, есть множество сетевых запросов, которые занимают много времени и не возвращают никаких новых данных.

введите здесь описание изображения

Использование записи временной шкалы, чтобы получить некоторые подробности об обработке на стороне клиента.

введите здесь описание изображения

введите здесь описание изображения

Клиентская сторона не так сильно страдает в представлении, которое я вижу, но без данных трудно реально оценить.

Вы можете увидеть, взяв временную шкалу, а затем увеличив часть записанных данных, какие фактические функции были вызваны и сколько времени они заняли. Есть также хорошие расширения для проверки $watchers в угловых

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

Вы можете использовать синтаксис {{::bindOnce}}, чтобы уменьшить количество наблюдателей, если привязки обновляются только один раз (полезно в ng-repeats много раз). Это помогает сократить время дайджеста, поскольку нужно проверять меньше наблюдателей на наличие изменений. Если у вас очень длинный список элементов (1000), то использование какого-либо виртуального скроллера или пейджинга UI-компонента полезно, чтобы избежать создания 1000*элементов на строку элементов в DOM.

На стороне сервера вы можете использовать плагин/модуль xdebug для сбора данных профилирования со стороны сервера и можете использовать kcachegrind для оценки этих данных, чтобы найти, где сервер тратит больше всего времени, но также можно использовать какое-то кэширование на стороне сервера и там более разумная логика, чтобы избежать постоянного обращения к базе данных, если ничего не изменилось (возможно, изучите использование Redis или изучите memcached для ускорения этих действий на стороне сервера или посмотрите, не просто ли это сетевая задержка).

Смена языков или фреймворков без фактического профилирования для получения данных о том, что именно является медленным, не является хорошим шагом, IMO будет просто прыгать между тем, что является новой популярностью, не понимая, почему и имеет ли это значение.

Ниже приведен пример относительно быстрого ответа PHP-скрипта. По сути, он ничего не делает, кроме как выдает жестко закодированный ответ JSON, используя Redis или memcached, не будет много дополнительных накладных расходов, чтобы получить ответ, особенно пустой.

введите здесь описание изображения

person shaunhusain    schedule 30.11.2017
comment
Спасибо за подробный ответ, но я очень надеялся на изменение способа оказания услуги. - person Abdul Amoud; 01.12.2017
comment
@AbdulAmoud ответ: это зависит от того, и вам нужно собрать больше данных, чтобы определить, что на самом деле работает медленно. Я оставил несколько предложений по общим проблемам/решениям, но серебряной пули нет. - person shaunhusain; 01.12.2017
comment
Ничего действительно медленного, кроме случайного мерцания. У меня не было плохих отзывов. Одна вещь, однако, если вы делаете запись и пытаетесь выбрать ее, чтобы вы могли ее скопировать, выбор исчезает до того, как пользователь получает возможность скопировать, и это происходит потому, что запись в основном исчезает и заменяет себя. Это на самом деле хорошо на данный момент, но я стремлюсь создавать приложения, которые потенциально будут использоваться тысячами людей, а это, конечно, не годится. - person Abdul Amoud; 01.12.2017
comment
500 мс для получения пустого ответа - это довольно медленно, мой сервер, дающий довольно прямой ответ, занимает около 50 мс, если вы ожидаете, что что-то произойдет в заданном временном промежутке, тогда вам нужно думать о медленном с точки зрения этого окна. Для выполнения сценария на стороне клиента более 16 мс выполнения на кадр означает, что кадры длиннее 1/60 секунды, что означает, что вы не получаете 60 кадров в секунду, время относительно. Что касается мерцания, если бы вы не заменяли элементы, когда данные не меняются, у вас не было бы этой проблемы. - person shaunhusain; 01.12.2017
comment
Также относительно мерцания, если вы можете воспроизвести проблему, которую вы видите в jsfiddle или plnkr, или где-то еще, куда ее можно ткнуть, тогда я могу попытаться решить конкретную проблему, но опять же не серебряная пуля, это просто зависит от того, что вы делаете - person shaunhusain; 01.12.2017
comment
если бы вы не заменяли элементы, когда данные не меняются, у вас не было бы этой проблемы. Это именно то, чего я пытаюсь избежать - person Abdul Amoud; 01.12.2017
comment
@AbdulAmoud совершенно верно, я думаю, что это можно / нужно обрабатывать в нескольких местах. На стороне сервера было бы хорошо проверить наличие новых данных в БД или какой-либо более быстрый кеш, чтобы увидеть, изменилась ли БД, прежде чем даже попасть в БД, чтобы она могла давать быстрые ответы. На стороне клиента можно получить ответ, и если он указывает, что изменений не было, можно избежать обновления рассматриваемой коллекции. - person shaunhusain; 01.12.2017
comment
Наличие актуальных данных без зацикливания запроса. - person Abdul Amoud; 01.12.2017
comment
Если вы не обновите объект, к которому привязано представление, то представление не будет обновляться, я думаю, это длинная история :) То, как вы получаете данные, на самом деле не так важно, но вызовы $http.get действительно вызывают вызов $digest, который заставляет любых наблюдателей срабатывать, поэтому, если вы можете уменьшить их, это тоже было бы здорово (вы также можете выполнять вызовы ajax вне контекста angular, обходя $http, но затем вам нужно вручную запускать $digest при изменении модели) - person shaunhusain; 01.12.2017

$http.get уже асинхронно! Асинхронная функция — это просто любая функция, выполнение которой завершается в неизвестное время в будущем.

То, что вы действительно пытаетесь сделать, называется долгий опрос. Именно здесь вы периодически отправляете запрос на свой сервер для получения последних данных, и есть несколько причин, по которым это не очень хорошая идея (включая мерцание и высокую загрузку ЦП, о которых вы говорили).

Я знаю, вы сказали, что не хотите, чтобы кто-то предлагал другие фреймворки, но попытка написать свой собственный фреймворк, который будет уведомлять клиента об обновлении базы данных, является монументальной задачей. Мы не можем дать вам короткий фрагмент кода, который даст вам эту функциональность только с помощью PHP и Javascript.

Однако вы можете попробовать создать свой собственный код с помощью WebSockets. Это самый простой, не связанный с фреймворком способ связи между сервером и клиентом так, как вы предлагаете.

person Pop-A-Stash    schedule 30.11.2017
comment
Что я имею в виду под другими фреймворками, так это предложить отказаться от angular 1.x и/или php и начать все сначала с новыми фреймворками. Я не против добавить к тому, что у меня уже есть. - person Abdul Amoud; 30.11.2017
comment
Ок, отлично. Взгляните на Ratchet (socketo.me) для PHP. Это должно заставить вас начать. - person Pop-A-Stash; 30.11.2017
comment
@AbdulAmoud PHP — это язык, JS — это язык, Angular — это фреймворк, просто чтобы уточнить. Кроме того, способ опроса очень неэффективен, особенно если задержка в сети оказывается близкой к вашему интервалу в 500 мс. Другая проблема заключается в том, что вы используете $http, который автоматически запускает дайджест, и вы заменяете массив каждый раз, независимо от того, изменилось что-то или нет. Если вы отправляете время последнего изменения и в ответе указываете, изменились ли данные, у вас будет гораздо меньше мерцания. Используйте инструменты Chrome для профилирования и временной шкалы. - person shaunhusain; 30.11.2017
comment
Я сомневаюсь, что получение данных более эффективным способом будет иметь слишком большое значение, похоже, в основном проблемы с тем, как написан код на стороне клиента, в настоящее время его просто нужно оптимизировать. - person shaunhusain; 30.11.2017
comment
Я просматривал веб-сайт socket.io, и похоже, что он фокусируется только на node.js. - person Abdul Amoud; 30.11.2017
comment
Если вы можете где-то временно показать свой сайт, чтобы мы могли посмотреть, я могу дать вам свой .02 из профилирования, но без рук трудно сказать, где именно все становится очень медленным (может быть, отсутствие виртуальной прокрутки и слишком много элементов dom /watchers или что-то еще) Если нет, можно было бы примерно воссоздать код на стороне клиента, используя flickr api или какой-либо другой общедоступный. - person shaunhusain; 30.11.2017
comment
ОК, да, я согласен с этим ответом, теперь вы пытаетесь отправить слишком много данных слишком быстро, большинство этих сетевых запросов занимают более 500 мс и выполняются в постоянном потоке, который будет действительно неэффективным как в сети, так и на клиент... насколько в действительности должны быть эти данные в реальном времени? мы говорим о высокоскоростной торговле или чате почти в реальном времени? Видим поток запросов, в теле ответа которых ничего нет, но все же требуется некоторое время для обработки на стороне сервера. - person shaunhusain; 30.11.2017
comment
Скорее всего, я не собираюсь сильно менять этот проект, я создал систему чата на основе решения, которое у меня есть из вопроса. Но я хочу, чтобы это было более эффективно (для меня это все упражнения). Так что да, звонки должны быть такими частыми, как 500 мс или, по крайней мере, 1000 мс. Я не против бросить работу на сервер, я просто не хочу, чтобы клиентская сторона страдала. Причина, по которой мне нужно простое решение, не в том, что я ленив, я имею дело с хостом, который не дает мне root-доступа, поэтому мне нужно решение, которое работает с тем, что у меня есть. - person Abdul Amoud; 30.11.2017