Javascript — асинхронные ajax запросы на примерах

Отправка изображения или файла ajax-запросом через jQuery

Задача отправки файла или изображения на сервер без перезагрузки страницы довольно часто возникает. В этом примере разберу сразу 2 фишки: выбор файла по нажатию на кнопку, которая может быть оформлена как угодно, и отображение прогресса при передаче файла на сервер ajax-запросом.

html-код будет такой:

<button id="addfile"><span>Загрузить изображение</span><input type="file" id="load_file" value=""></button>

css код:

#addfile {
  position: relative;
  overflow: hidden;
  width: 180px;
  height: 34px;
}
#load_file {
  position: absolute;
  top: 0;
  left: 0;
  width: 180px;
  height: 34px;
  font-size: 0px;
  opacity: 0;
  filter: alpha(opacity:0);
}
#load_file:hover {
  cursor: pointer;
}

Суть идеи в том, что поверх кнопки выводится стандартный input для выбора файла, но он полностью прозрачен и имеет такие же размеры как кнопка. Таким образом, пользователь видит кнопку button, но когда наводит на нее курсор, фактически наводит на input. Соответственно, когда он нажимает на кнопку, на самом деле нажимается input выбора файла. Для того, чтобы не мигал курсор после выбора файла, размер шрифта задан 0px.

Теперь javascript код отправки файла на сервер с отображением прогресса:

$(function() {
  $('#load_file').on('change', loadfile);
});

function loadfile() {
  $('#addfile span').html('Загружено 0 %');
  files = $('#load_file').files;
  var form = new FormData();
  form.append('upload', files);
  $.ajax({
    url: '<url-адрес>',
    type: 'POST',
    data: form,
    cache: false,
    processData: false,
    contentType: false,
    xhr: function() {
      var myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        myXhr.upload.addEventListener('progress',ShowProgress, false);
      }
      return myXhr;
    },
    complete: function(data){
      $('#addfile span').html('Загрузить изображение');
      $('#load_file').val('');
    },
    success: function(message){
      alert(message);
    },
    error: function(jqXHR, textStatus, errorThrown) {
      alert(textStatus+' '+errorThrown);
    }
  });
}

function ShowProgress(e) {
  if(e.lengthComputable){
    $('#addfile span').html('Загружено '+Math.round(100*e.loaded/e.total)+' %');
  }
}

При загрузке файла на сервер в кнопке будет показываться сколько % уже передано на сервер. После завершения загрузки название кнопки возвращается как было, а значение input-а с файлом устанавливается пустым, чтобы можно было снова выбирать новый файл.

Пример серверной части на php (по просьбе Евгения):

  $message = '';
  if (empty($_FILES) || $_FILES == "none") {
    $message = 'Вы не выбрали файл';
  } else if ($_FILES == 0 || $_FILES > 9437184) {
    $message = 'Размер файла не соответствует нормам (максимум 9 Мб)';
  } else if (($_FILES != 'image/jpeg') && ($_FILES != 'image/pjpeg') &&
             ($_FILES != 'image/gif') && ($_FILES != 'image/png')) {
    $message = 'Допускается загрузка только картинок JPG, GIF и PNG.';
  } else if (!is_uploaded_file($_FILES)) {
    $message = 'Что-то пошло не так. Попытайтесь загрузить файл ещё раз.';
  } else {
    $ftype = $_FILES;
    $fname = 'newname_image.'.($ftype == 'image/gif' ? 'gif' : ($ftype == 'image/png' ? 'png' : 'jpg'));
    if (move_uploaded_file($_FILES, $_SERVER.'/files/'.$fname)) {
      $message = 'Изображение успешно загружено.';
    } else {
      $message = 'Что-то пошло не так. Попытайтесь загрузить файл ещё раз.';
    }
  }
  exit($message);

Информация о загруженном изображении будет содержаться в $_FILES, т.к. скриптом файл добавлялся так: form.append(‘upload’, files); Соответственно, всё что требуется от php-программы — это проверить что файл соответствует ожидаемым параметрам, перенести файл в нужную папку (в примере в папку files) под нужным именем (в примере newname_image) и вернуть в браузер ответ, который в моем примере просто выводится пользователю командой alert(message);

jQuery $.post() Method

The method requests data from the server using an HTTP POST request.

Syntax:

$.post(URL,data,callback);

The required URL parameter specifies the URL you wish to request.

The optional data parameter specifies some data to send along with the
request.

The optional callback parameter is the name of a function to be executed
if the request succeeds.

The following example uses the method to send some data along with the
request:

Example

$(«button»).click(function(){
  $.post(«demo_test_post.asp»,
  {
    name: «Donald Duck»,
    city: «Duckburg»
  },
  function(data, status){
    alert(«Data: » + data + «\nStatus: » + status);
  });
});

The first parameter of is the URL we wish to request («demo_test_post.asp»).

Then we pass in some data to send along with the request (name and city).

The ASP script in «demo_test_post.asp» reads the parameters,
processes them, and returns a result.

The third
parameter is a callback function. The first callback parameter holds the content of
the page requested, and the second callback parameter holds the status of
the request.

Tip: Here is how the ASP file looks like («demo_test_post.asp»):

<%
dim fname,city
fname=Request.Form(«name»)
city=Request.Form(«city»)
Response.Write(«Dear » & fname & «. «)
Response.Write(«Hope you live well in » & city & «.»)
%>

Пример 3. Передача синхронного AJAX запроса на сервер с помощью метода POST

В этом примере данные на сервер будем передавать с помощью метода POST (в теле HTTP-запроса). В методе POST данные (параметры) передаются не в составе URL (метод GET), а в теле, которое мы посылаем серверу через . Т.е. для того чтобы передать данные с помощью POST, мы их должны поместить в качестве параметра методу . Кроме того, при отправке данных с помощью POST необходимо также указать заголовок Content-Type, содержащий кодировку с помощью которой мы зашифровали данные. Это необходимо сделать для того чтобы сервер знал как обработать (расшифровать), пришедшие к нему данные (запрос).

<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>JavaScript AJAX</title>
    <style>
      span {
        font-weight: bold;
        color: red;
      }
    </style>
  </head>
  <body>
    <p>Введите имя и нажмите на кнопку "Получить...".</p> 
    <input id="nameUser" type="text" placeholder="Введите имя">
    <input id="button" type="button" value="Получить ответ с сервера">
    <p>Ответ (AJAX): <span id="answer"></span></p>
    <script src="script.js"></script>
  </body>
</html> 
// получить элемент, имеющий id="button"
var button = document.getElementById("button");
// подпишемся на событие click элемента 
button.addEventListener("click",function() {
  // создадим объект XMLHttpRequest
  var request = new XMLHttpRequest();
  // параметры запроса
  var params = 'name=' + encodeURIComponent(document.getElementById("nameUser").value);
  // настраиваем запрос: POST - метод, ajaxpost.php - URL-адрес, по которому посылается запрос, false - синхронный запрос
  request.open('POST','ajaxpost.php',false);
  // указываем заголовок Content-Type, содержащий кодировку 
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
  // отправляем данные на сервер с помощью метода send
  request.send(params);
  // если статус ответа 200 (OK) то
  if (request.status==200) {
    // выведем в элемент, имеющий id="answer", ответ сервера
    document.getElementById("answer").innerHTML = request.responseText;
  }	
})
<?php
// если в ассоциативном массиве $_POST существует ключ name
if (isset($_POST)) {
  // присвоим переменной $name значение из ассоциативного массива POST соответсвующее ключу name
  $name = $_POST;
  // выведем строку (ответ сервера)
  echo "Привет, ".$name."!";
}     
?>

jQuery $.get() Method

The method requests data from the server with an HTTP GET request.

Syntax:

$.get(URL,callback);

The required URL parameter specifies the URL you wish to request.

The optional callback parameter is the name of a function to be executed
if the request succeeds.

The following example uses the method to retrieve data from a file on
the server:

Example

$(«button»).click(function(){
  $.get(«demo_test.asp», function(data, status){
    alert(«Data: » + data + «\nStatus: » + status);
  });
});

The first parameter of is the URL we wish to request («demo_test.asp»).

The second
parameter is a callback function. The first callback parameter holds the content of
the page requested, and the second callback parameter holds the status of
the request.

Tip: Here is how the ASP file looks like («demo_test.asp»):

<%
response.write(«This is some text from an external ASP file.»)
%>

Создание асинхронного AJAX запроса (метод GET)

Рассмотрим создание асинхронного AJAX запроса на примере, который будет после загрузки страницы приветствовать
пользователя и отображать его IP-адрес.

Для этого необходимо создать на сервере 2 файла в одном каталоге:

  1. – HTML-страница, которая будет отображаться пользователю. В этой же страницы поместим
    скрипт, который будет осуществлять все необходимые действия для работы AJAX на стороне клиента.
  2. – PHP-файл, который будет обрабатывать запрос на стороне сервера, и формировать ответ.
    Начнём разработку с создания основной структуры файла
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>
  <div id="welcome"></div>
  <script>
  // Здесь поместим код JavaScript, который будет отправлять запрос на сервер, получать его и обновлять содержимое страницы. Всё это будет работать без перезагрузки страницы

</script>
</body>
</html>  

Рассмотрим последовательность действий, которые необходимо выполнить на стороне клиента (в коде JavaScript):

  1. Подготовим данные, необходимые для выполнения запроса на сервере. Если для выполнения запроса на сервере данные
    никакие не нужны, то данный этап можно пропустить.

  2. Создадим переменную, которая будет содержать экземпляр объекта XHR (XMLHttpRequest).

  3. Настроим запрос с помощью метода .

    Указываются следующие параметры:

    • Метод, с помощью которого будет посылаться запрос на сервер (GET, POST).
    • URL-адрес, который будет обрабатывать запрос на сервере.
    • Тип запроса: синхронный (false) или асинхронный (true).
    • Имя и пароль при необходимости.
  4. Подпишемся на событие объекта XHR и укажем обработчик в виде анонимной или
    именованной функции. После этого создадим код внутри этой функции, который будет проверять состояние ответа, и
    выполнять определённые действия на странице. Ответ, который приходит с сервера, всегда находится в свойстве
    .

    Дополнительно с проверкой значения свойства числу 4, можно проверять и значение свойства
    . Данное свойство определяет статус запроса. Если оно равно 200, то всё . А
    иначе произошла ошибка (например, 404 – URL не найден).

  5. Отправим запрос на сервер с помощью метода .

    Если используем для отправки запроса метод GET, то передавать данные в параметр данного метода не надо. Они
    передаются в составе URL.

    Если используем для отправки запроса метод POST, то данные необходимо передать в качестве параметра методу
    . Кроме этого, перед вызовом данного метода необходимо установить заголовок Content-Type, чтобы
    сервер знал в какой кодировке пришёл к нему запрос и смог его расшифровать.

Содержимое элемента :

// 2. Создание переменной request
var request = new XMLHttpRequest();
// 3. Настройка запроса
request.open('GET','processing.php',true);
// 4. Подписка на событие onreadystatechange и обработка его с помощью анонимной функции
request.addEventListener('readystatechange', function() {
  // если состояния запроса 4 и статус запроса 200 (OK)
  if ((request.readyState==4) && (request.status==200)) {
    // например, выведем объект XHR в консоль браузера
    console.log(request);
    // и ответ (текст), пришедший с сервера в окне alert
    console.log(request.responseText);
    // получить элемент c id = welcome
    var welcome = document.getElementById('welcome');
    // заменить содержимое элемента ответом, пришедшим с сервера
    welcome.innerHTML = request.responseText;
  }
}); 
// 5. Отправка запроса на сервер
request.send();

В итоге файл будет иметь следующий код:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>

  <div id="welcome"></div>

<script>
window.addEventListener("load",function() {
  var request = new XMLHttpRequest();
  request.open('GET','processing.php',true);
  request.addEventListener('readystatechange', function() {
    if ((request.readyState==4) && (request.status==200)) {
      var welcome = document.getElementById('welcome');
      welcome.innerHTML = request.responseText;
    }
  });
request.send();
});
</script>

</body>
</html>

На сервере (с помощью php):

  1. Получим данные. Если данные посланы через метод , то из глобального массива
    . А если данные переданы с помощью метода , то из глобального
    массива .
  2. Используя эти данные, выполним некоторые действия на сервере. В результате которых получим некоторый ответ.
    Выведем его с помощью .
<?php
$output = 'Здравствуйте, пользователь! ';
if ($_SERVER) {
  $output .= 'Ваш IP адрес: '. $_SERVER;
}
else {
 $output .= 'Ваш IP адрес неизвестен.';
}
echo $output;

Логичное подключение AJAX хуков

Я не стал усложнять чтение и не говорил, как правильно подключать AJAX через хуки в коде. Впрочем все что написано ниже не обязательно, потому что работать будет и так, но это рекомендуется.

Функции обработчики установленные хукам:

  • wp_ajax_(action)
  • wp_ajax_nopriv_(action) 

Оба хука всегда удовлетворяют условию wp_doing_ajax():

if( wp_doing_ajax() ){}

// до версии WP 4.7 
if( defined('DOING_AJAX') ){}

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

Используя это правило, можно не подключать хуки там где в этом нет смысла. Например, при генерации страницы шаблона или страницы админки. Эта маленькая деталь добавит больше логики в код и в некоторых случаях может избавить от багов.

Пример того, как рекомендуется подключать все AJAX хуки.

// подключаем AJAX обработчики, только когда в этом есть смысл
if( wp_doing_ajax() ){
	add_action('wp_ajax_myaction', 'ajax_handler');
	add_action('wp_ajax_nopriv_myaction', 'ajax_handler');
}

// или так до WP 4.7
if( defined('DOING_AJAX') ){
	add_action('wp_ajax_myaction', 'ajax_handler');
	add_action('wp_ajax_nopriv_myaction', 'ajax_handler');
}

В этом случае хуки будут подключены только во время AJAX запроса и не будут подключены при простом посещении фронта, админки, REST или CRON запросе.

Напомню также, что данные отправляемые с фронтэнда на файл wp-admin/admin-ajax.php обработаются указанной в хуке произвольной функцией ajax_handler(), независимо авторизован пользователь или нет.

Значения параметров

Параметр Описание
url Строка, содержащая URL адрес, на который отправляется AJAX запрос. Обязательный параметр.
data Объект или строка, которые будут отправлены на сервер вместе с AJAX запросом. Данные, отправляемые на сервер добавляются к URL в строке запроса. Если значение параметра данных является простым объектом, то он кодируется и преобразуется в строку URL, прежде чем он будет добавлен к URL адресу. Необязательный параметр.
success Функция обратного вызова, которая вызывается если AJAX запрос выполнится успешно. Необязательный параметр. Функция принимает следующие параметры:

  • data — данные возвращенные с сервера.
  • textStatus — строка описывающая статус запроса.
  • jqXHR — объект jqXHR (до версии jQuery 1.4.x объект XMLHttpRequest).
dataType Определяет тип данных, который вы ожидаете получить от сервера. Если тип данных не указан, то jQuery будет пытаться определить его на основе типа MIME из ответа (XML тип MIME приведет к получению XML, с версии jQuery 1.4 json будет давать объект JavaScript, script будет выполнять скрипт, а все остальное будет возвращено в виде строки). Необязательный параметр.

Доступные типы (результат передается в качестве первого аргумента в функцию обратного вызова success):

  • «xml» — возвращает XML документ, который может быть обработан с помощью jQuery.
  • «html» — возвращает HTML как обычный текст, теги <script> будут обработаны и выполнены после вставки в объектную модель документа (DOM).
  • «script» — расценивает ответ как JavaScript и возвращает его как обычный текст. Отключает кэширование с помощью добавления параметра к строке запроса _=, даже если парамета cache имеет значение true. Это превратит метод POST в GET для кроссдоменных запросов.
  • «json» — расценивает ответ как JSON и возвращает объект JavaScript. Кроссдоменные «json» запросы преобразуются в «jsonp», если в параметрах запроса не указано jsonp: false.
    Данные JSON парсятся в строгом порядке и должны соответствовать общепринятому формату, любой некорректный JSON отвергается и выдается ошибка. С версии jQuery 1.9, пустой ответ не принимается, сервер должен вернуть в качестве ответа NULL, или {}.
  • «jsonp» — загружает данные в формате JSON, используя при этом формат загрузки JSONP. Добавляет дополнительный параметр «?callback=?» в конец URL адреса для указания имени функции обработчика. Отключает кэширование путем добавления параметра _= к URL адресу,даже если парамета cache имеет значение true.
  • «text» — обычная текстовая строка.
  • несколько значений — значения разделяются пробелом. Начиная с версии 1.5, jQuery может преобразовать тип данных, который получен в Content-Type заголовка, в тип данных, который вам требуется. Например, если вы хотите, чтобы текстовый ответ был расценен как XML, используйте «text XML» для этого типа данных. Вы также можете сделать JSONP запрос, получить его в виде текста и интерпретировать его в формате XML: «jsonp text XML». Следующая строка позволит сделать тоже самое: «jsonp XML», jQuery будет пытаться конвертировать из JSONP в XML, после неудачной попытки попытается преобразовать JSONP в текст, а затем из текста уже в XML.

Синхронный запрос

Чтобы выполнить синхронный запрос, измените третий параметр в методе на :

xhttp.open(«GET», «ajax_info.txt», false);

Иногда для быстрого тестирования используются async = false. Вы также найдете синхронные запросы в более старом коде JavaScript.

Так как код будет ждать завершения работы сервера, нет необходимости в функции :

Пример

xhttp.open(«GET», «ajax_info.txt», false);
xhttp.send();
document.getElementById(«demo»).innerHTML = xhttp.responseText;

Синхронный XMLHttpRequest (async = false) не рекомендуется, так как JavaScript перестанет выполняться до тех пор, пока не будет готов ответ сервера.
Если сервер занят или работает медленно, приложение зависнет или остановится.

Синхронный XMLHttpRequest находится в процессе удаления из веб стандарта, но этот процесс может занять много лет.

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

jQuery синтаксис:

Синтаксис 1.0:

$.post( url, data, success, dataType );

url - String
data - PlainObject, или String 
success - Function( PlainObject data, String textStatus, jqXHR jqXHR )
dataType - String

Синтаксис 1.12/2.2:

$.post( {settings} ); // параметры запроса передаются в объекте

settings - PlainObject

Страницы, загруженные функцией $.post() никогда не кэшируются, по этой причине значения параметров cache (определяет будут ли кэшироваться страницы, по умолчанию true) и ifModified (проверяет поля заголовка Last-Modified, по умолчанию false) jQuery функции .ajaxSetup() (устанавливает значения по умолчанию для будущих запросов AJAX) не повлияют на эти запросы.

Делаем запрос GET с помощью $.get()

Метод jQuery предоставляет легкий и удобный способ сделать простой запрос AJAX. Он выполняет запрос с помощью метода HTTP GET (используется для получения URL, например страниц и изображений), вместо метода POST (который традиционно используется для отправки данных формы).

В простейшей форме можно вызвать метод так:

$.get( url );

…где является адресом URL ресурса, от которого ожидается ответ. Обычно это скрипт на стороне сервера, который выполняет какие-нибудь действия и может возвращать некие данные:

$.get( "http://example.com/getForecast.php" );

…хотя можно также запросить статический документ:

$.get( "http://example.com/mypage.html" );

При запросе URL, вы можете отправить данные с запросом. Вы можете передать данные в строке запроса, так же как и при обычном запросе GET:

$.get( "http://example.com/getForecast.php?city=rome&date=20120318" );

Корректно будет сделать то же самое передав объект данных в качестве второго параметра методу . Объект данных должен содержать информацию в виде пар имя свойства/значение свойства. Например:

var data = { city: "rome", date: "20120318" };
$.get( "http://example.com/getForecast.php", data );

В качестве альтернативы вы можете передать данные методу как строку:

var data = "city=rome&date=20120318";
$.get( "http://example.com/getForecast.php", data );

Защита: используем nonce и проверяем права

Нет острой необходимости проверять AJAX запрос, если он потенциально не опасный. Например, когда он просто получает какие-то данные. Но когда запрос удаляет или обновляет данные, то его просто необходимо дополнительно защитить с помощью nonce кода и проверкой прав доступа.

Разработчики часто ленятся ставить такую защиту, получая самый неожиданный результат. Недобросовестные пользователи могут каким-либо образом заставить юзера с правами сделать то что им нужно и в итоге навредить сайту над которым вы работали долгие месяцы, годы.

Существует два вида защиты, которые нужно использовать в AJAX запросах в большинстве случаев.

1. Код nonce (случайный код)

Nonce — это уникальная строка, которая создается и используется один раз — одноразовое число. Nonce проверка используется, когда нужно убедится, что запрос был послан с указанного «места».

В WordPress есть функции wp_create_nonce() и check_ajax_referer() — это базовые функции для создания и последующей проверки nonce кода. С их помощью мы и будем создавать защиту nonce для AJAX запросов.

Для начала создадим nonce код:

add_action( 'wp_enqueue_scripts', 'myajax_data', 99 );
function myajax_data(){

	wp_localize_script('twentyfifteen-script', 'myajax', 
		array(
			'url' => admin_url('admin-ajax.php'),
			'nonce' => wp_create_nonce('myajax-nonce')
		)
	);  

}

это название основного скрипта темы (см. выше), который подключается на сайте с помощью wp_enqueue_script().

Затем, в AJAX запросе добавим переменную с кодом nonce:

var ajaxdata = {
	action     : 'myajax-submit',
	nonce_code : myajax.nonce
};
jQuery.post( myajax.url, ajaxdata, function( response ) {
	alert( response );
});

Теперь, в обработке заброса необходимо проверить nonce код:

add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
function myajax_submit(){
	// проверяем nonce код, если проверка не пройдена прерываем обработку
	check_ajax_referer( 'myajax-nonce', 'nonce_code' );
	// или так
	if( ! wp_verify_nonce( $_POST, 'myajax-nonce' ) ) die( 'Stop!');

	// обрабатываем данные и возвращаем
	echo 'Возвращаемые данные';

	// не забываем завершать PHP
	wp_die();
}

check_ajax_referer() работает на основе функции wp_verify_nonce() и по сути является её оберткой для AJAX запросов.

Обратите внимание, что в данном случае Nonce код создается в HTML коде. А это значит, что если у вас установлен плагин страничного кэширования, то этот код может и наверняка будет устаревать к моменту очередного AJAX запроса, потому что HTML код кэшируется..

2. Проверка прав доступа

Тут AJAX запросы будут срабатывать только для пользователей с правом указанным правом, например author. Для всех остальных, включая неавторизованных пользователей, AJAX запрос вернет ошибку.

Особенность тут в том, что не авторизованные пользователи тоже должны видеть сообщение об ошибке при AJAX запросе. Поэтому для них тоже нужно обрабатывать запрос и вернуть сообщение об ошибке:

add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
function myajax_submit(){
	// проверяем nonce код, если проверка не пройдена прерываем обработку
	check_ajax_referer( 'myajax-nonce', 'nonce_code' );

	// текущий пользователь не имеет права автора или выше
	if( ! current_user_can('publish_posts') )
		die('Этот запрос доступен пользователям с правом автора или выше.')

	// ОК. У юзера есть нужные права!

	// Делаем что нужно и выводим данные на экран, чтобы вернуть их скрипту

	// Не забываем выходить
	wp_die();
}

Код PHP-файла

PHP-файд должен сформировать нам случайное число от 0 до 4 (индексы в массивах в PHP начинаются с 0) и выдать на основе этого числа и пришедшей в параметре   категории  id изображения из массива .

Выбираем случайную картинку из категории в PHP

PHP

<?php
//print_r($_POST); //имеет смысл вывести на начальном этапе создания php-файла, чтобы увидеть,
//какие данные приходят. Затем удалить
if(!isset($_POST)) die(‘Нет данных для отображения картинки’);
$param = $_POST;
$randomId = rand ( 0 , 4 ); //случайное число от 0 до 4
//массив, содержащий id картинок с unspash.com
$imgArr = array(
‘nature’ => array(‘4rDCa5hBlCs’, ‘cssvEZacHvQ’, ‘GVnUVP8cs1o’, ‘lpjb_UMOyx8′,’01_igFr7hd4’),
‘people’ => array(‘IBaVuZsJJTo’, ‘sibVwORYqs0’, ‘nPz8akkUmDI’, ’98Elr-LIvD8′,’tSlvoSZK77c’),
‘animals’ => array(‘nKC772R_qog’, ‘A81818EFqGQ’, ‘I3C1sSXj1i8′, ’39SHYToxfiQ’, ‘_9a-3NO5KJE’),
‘objects’=> array(‘qcqmS0JG58Q’, ‘Nv4QHkTVEaI’, ‘KD3YDXJd9T8’, ‘cdnhg0csyAM’, ‘_yVRLC75Ma8’),
);

//Вывод тега изображения с нужным адресом и размером
echo ‘<img src=»https://source.unsplash.com/’.$imgArr.’/500×300″ alt=»‘.$param.'»>’;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<?php
//print_r($_POST); //имеет смысл вывести на начальном этапе создания php-файла, чтобы увидеть,
//какие данные приходят. Затем удалить

if(!isset($_POST’typeImg’))die(‘Нет данных для отображения картинки’);

$param=$_POST’typeImg’;

$randomId=rand(,4);//случайное число от 0 до 4

//массив, содержащий id картинок с unspash.com

$imgArr=array(

‘nature’=>array(‘4rDCa5hBlCs’,’cssvEZacHvQ’,’GVnUVP8cs1o’,’lpjb_UMOyx8′,’01_igFr7hd4′),

‘people’=>array(‘IBaVuZsJJTo’,’sibVwORYqs0′,’nPz8akkUmDI’,’98Elr-LIvD8′,’tSlvoSZK77c’),

‘animals’=>array(‘nKC772R_qog’,’A81818EFqGQ’,’I3C1sSXj1i8′,’39SHYToxfiQ’,’_9a-3NO5KJE’),

‘objects’=>array(‘qcqmS0JG58Q’,’Nv4QHkTVEaI’,’KD3YDXJd9T8′,’cdnhg0csyAM’,’_yVRLC75Ma8′),

);

 
//Вывод тега изображения с нужным адресом и размером

echo'<img src=»https://source.unsplash.com/’.$imgArr$param$randomId.’/500×300″ alt=»‘.$param.'»>’;

В заголовках запроса (Headers) мы видим передачу одного параметра . При переключении на вкладку ответа (Response) можно увидеть сформированный тег, а в Preview — и саму картинку.

Заголовок post-запроса

Ответ сервера

На самом деле для этого примера совсем необязательно было подтягивать AJAX-запрос и его обработку в PHP-файле — с этим вполне бы справился и один JavaScript/jQuery, но, если расширить задачу до случайного выбора файла изображения из определенной категории в базе данных, — здесь уже точно понадобится связка AJAX-PHP.

Просмотров:
53

Что такое асинхронный запрос AJAX?

Технология AJAX в основном используется для создания асинхронных запросов к серверу. Асинхронный запрос — это такой
запрос, который выполняется в фоновом режиме и не мешает пользователю взаимодействовать со страницей.

При отправке асинхронного запроса, браузер (страница) не «замораживается», т.е. с ней, как и прежде, можно работать.
Но тогда как узнать, когда придёт ответ с сервера. Чтобы это определить, необходимо отслеживать свойство браузера
(состояние готовности). Данное свойство содержит число, по значению которого можно судить о
том, в какой стадии находится запрос. В следующей таблице приведены основные значения свойства
и соответствующие им состояния.

Значение свойства readyState Описание
запрос не инициализирован
1 выполнена настройка запроса
2 запрос отправлен
3 запрос находится в процессе обработки на сервере
4 запрос завершён

Т.е. получается, что нам необходимо отследить, когда значение у свойства будет равно 4. Это
будет означать то, что на отправленный запрос, пришёл ответ с сервера. Остальные значения на практике используются
довольно редко, и некоторые браузеры могут их не поддерживать.

Для того чтобы определить на какой стадии находится запрос, необходимо использовать событие объекта XMLHttpRequest
. Данное событие происходит каждый раз, когда изменяется значение свойства
. Следовательно, в обработчике этого события (неименованной или именованной функции) можно
прописать действия, которые будут проверять равно ли данное свойство 4 и если равно, то например, вывести ответ
сервера на страницу.

HTML-разметка примера

Поскольку какой-либо текст не является предметом данной статьи, то в html-файле мы разместим только форму, для предзагрузчика, который изначально спрятан () и пустой с классом, позволяющим :

html-разметка примера с ajax-загрузкой случайной картинки

<body>
<form id=»testPost» class=»small-form»>
<label>Выберите один из вариантов:</label>
<p><label for=»type1″><input type=»radio» name=»typeImg» id=»type1″ value=»nature»>Природа</label>
<label for=»type2″><input type=»radio» name=»typeImg» id=»type2″ value=»people»>Люди</label>
<label for=»type3″><input type=»radio» name=»typeImg» id=»type3″ value=»animals»>Животные</label>
<label for=»type4″><input type=»radio» name=»typeImg» id=»type4″ value=»objects»>Объекты</label></p>
<div><button class=»btn btn-info»>Готово</button></div>
</form>
<div class=»loader» style=»display: none»>
<div id=»loader-6″>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class=»text-center img-block»>
<!— здесь будет картинка или текст —>
</div>
<script src=»https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js»></script>
<script src=»post-ajax.js»></script>
</body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

23

<body>

<form id=»testPost»class=»small-form»>

<label>Выберитеодинизвариантов<label>

<p><label for=»type1″><input type=»radio»name=»typeImg»id=»type1″value=»nature»>Природа<label>

<label for=»type2″><input type=»radio»name=»typeImg»id=»type2″value=»people»>Люди<label>

<label for=»type3″><input type=»radio»name=»typeImg»id=»type3″value=»animals»>Животные<label>

<label for=»type4″><input type=»radio»name=»typeImg»id=»type4″value=»objects»>Объекты<label><p>

<div><button class=»btn btn-info»>Готово<button><div>

<form>

<div class=»loader»style=»display: none»>

<div id=»loader-6″>

<span><span>

<span><span>

<span><span>

<span><span>

<div>

<div>

<div class=»text-center img-block»>

<!—здесьбудеткартинкаилитекст—>

<div>

<script src=»https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js»></script>

<body>

Перед закрывающим тегом подключаем библиотеку jQuery (используем версию 3.5.1) с Google CDN или с другого ресурса, или из локальной папки. Затем подключаем наш файл post-ajax.js, в котором запишем основной код.

Создание асинхронного AJAX запроса (метод POST)

Изменим вышеприведённый пример. Теперь AJAX запрос к серверу будет выполняться после нажатию на кнопку. Он будет
получать имя, которое ввёл пользователь в элемент и отправлять его посредством метода POST на
сервер. После получения ответа с сервера, заменим им содержимое элемента на странице.

HTML:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>

  <div id="welcome">
    <label for="name">Имя:</label>
    <input type="text" id="name" placeholder="Например, Иван">
    <button id="send">Отправить</button>
  </div>

<script>
//после загрузки DOM-дерева страницы
document.addEventListener("DOMContentLoaded",function() {
  //получить кнопку
  var mybutton = document.getElementById('send');
  //подписаться на событие click по кнопке и назначить обработчик, который будет выполнять действия, указанные в безымянной функции
  mybutton.addEventListener("click", function(){
    //1. Сбор данных, необходимых для выполнения запроса на сервере
    var name = document.getElementById('name').value;
    //Подготовка данных для отправки на сервер
    //т.е. кодирование с помощью метода encodeURIComponent
    name = 'nameUser=' + encodeURIComponent(name);
    // 2. Создание переменной request
    var request = new XMLHttpRequest();
    // 3. Настройка запроса
    request.open('POST','processing.php',true);
    // 4. Подписка на событие onreadystatechange и обработка его с помощью анонимной функции
    request.addEventListener('readystatechange', function() {
      //если запрос пришёл и статус запроса 200 (OK)
      if ((request.readyState==4) && (request.status==200)) {
        // например, выведем объект XHR в консоль браузера
        console.log(request);
        // и ответ (текст), пришедший с сервера в окне alert
        console.log(request.responseText);
        // получить элемент c id = welcome
        var welcome = document.getElementById('welcome');
        // заменить содержимое элемента ответом, пришедшим с сервера
        welcome.innerHTML = request.responseText;
      }
    });
    // Устанавливаем заголовок Content-Type(обязательно для метода POST). Он предназначен для указания кодировки, с помощью которой зашифрован запрос. Это необходимо для того, чтобы сервер знал как его раскодировать.
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    // 5. Отправка запроса на сервер. В качестве параметра указываем данные, которые необходимо передать (необходимо для POST)
    request.send(name);
  });
});
</script>

</body>
</html>

PHP:

<?php
// создадим переменную для формирования ответа
$output ='';
// если в массиве пост есть ключ nameUser, то
if (isset($_POST)) {
  // в переменную name помещаем переданное с помощью запроса имя
  $name = $_POST;
  // добавляем в переменную output строку приветствия с именем
  $output .= 'Здравствуйте, '.$name.'! ';
  // добавляем в переменную output IP-адрес пользователя
  if ($_SERVER) {
    $output .= 'Ваш IP адрес: '. $_SERVER;
  }
  else {
   $output .= 'Ваш IP адрес неизвестен.';
  }
  // выводим ответ
  echo $output;
}
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector