Меню
✘Скрыть меню
Меню заработка
✘Скрыть меню
Загрузка.. nostroma.online from NOSTROMA - best life and beautiful workЭто ужасно тяжелая работа — ничего не делать – Оскар УайльдРешающую роль в работе играет не всегда материал, но всегда мастер – Максим ГорькийЯ слишком энергичен, чтобы работать – Марсель АшарЧто привлекло меня в карьере писателя? Отсутствие бумажной работы.Одни люди работают только для того чтобы работать, другие – для того, чтобы иметь возможность не работать в будущем.Занятие ерундой на рабочем месте развивает боковое зрение, слух и бдительность в целомСтоит статýя в лучах заката с огромным буем, в руках - граната.Друзья, если вы попались на лохотрон, не будьте эгоистами - предупредите других о таком сайте!Секрет гения — это работа, настойчивость и здравый смысл. Томас Эдисон
Меню заработка

Курсы JavaScript

Урок 16. AJAX, объект XMLHttpRequest

Содержание курса

Обратность и асинхронность

Для начала рассмотрим, чем отличается обратность от асинхронности: обратность - это когда действия происходят одно за другим, например, если вы используете метод map и подаёте ему на вход безымянную функцию обратного вызова. То же самое происходит при переборе списка.

В случае асинхронности действия выполняются не одно за другим, а по мере готовности, параллельно.

Обратность

В следующем примере ещё раз наглядно приведён пример обратности - использовано несколько методов (find, map, get, reduce) и каждый последующий из них использует результат, возвращённый предыдущим:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>Обратность</title>
			<script src="/library/jquery-3.0.0.min.js"></script>
		</head>
		<body>
		
		<button>Сумма</button>
		
		<ul>
			<li><input value="11"></li>
			<li><input value="22"></li>
			<li><input value="33"></li>
			<li><input value="44"></li>
			<li><input value="55"></li>
		</ul>
		
		<script>
			$('button').on('click', function(){
				var sum = $('ul').find('input')
					.map(function(){
						return +$(this).val();
					})
					.get()
					.reduce(function(a, b){
						return +a + +b;
					});
				$(this).text(sum);
			});
		</script>
		
		</body>
	</html>
Показать в браузере (откроется в новой вкладке)

В результате при нажатии на кнопку "сумма" мы запускаем цепочку всех этих методов и получаем сумму значений полей ввода в виде надписи на кнопке.

Пример обратности также ярко демонстрирует код примера в уроке 14, когда перебирается список из объектов, где каждый объект кроме последнего содержит внутри себя ссылку на следующий.

Асинхронность. AJAX

Асинхронность проявляется в том, что интерфейс реагирует на действия пользователя параллельно с обработкой ответов от сервера.

AJAX - Asynchronous JavaScript And XML - подход к клиентской разработке, суть которого в том, что при отправке запросов от клиента серверу данные в ответ приходят "порциями" и при этом вся текущая страница не перезагружается. Сегодня это фактический стандарт пользовательского интерфейса.

Наиболее наглядный пример асинхронных запросов к серверу - это подсказки, появляющееся в поле ввода поисковой системы, когда при вводе каждого символа открывается параллельное соединение с сервером поисковика и от туда приходят возможные варианты завершения ввода. Асинхронность в этом случае позволяет вам вводить следующий символ не зависимо от того, пришёл ответ подсказки от сервера или нет. Отсутвие асинхронности не позволило бы вам этого сделать - пришлось бы каждый раз при вводе символа дожидаться ответа подсказки, а влучае ошибок на стороне сервера - вводить запрос заново.

В настоящее время наиболее распространена нотация JSON, а не XML, поэтому правильнее было бы говорить AJAJ - Asynchronous JavaScript And JSON, а не AJAX.

При асинхронном AJAX запросе от сервера приходит заголовок

header('Content-Type: application/json'),

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

var obj = {'name':'Aleksandr', 'age':'33'};
obj;
/* Выведет: Object {name:'Aleksandr', age:'33'} */

JSON.stringify(obj);
/* Выведет: "Object {"name":"Aleksandr", "age":"33"}" */

О методе передачи данных GET

Каждый раз, когда вы нажимаете на гиперссылку или вводите адрес в адресную строку браузера, он отправляет запрос методом GET, при этом детали запроса видны прямо в адресной строке.

В адресах типа http://nostroma.online/courses/?cru=16 то, что находится после вопросительного знака называется Query String. Обратите внимание, что Query String состоит из пар (одной или нескольких) ключ=значение, если таких пар несколько, то они разделяются амперсандами (&):
http://nostroma.online/courses/?cru=16&vsr=5

Объект XMLHttpRequest

Для того, чтобы програмно отправлять асинхронные запросы и обрабатывать поступающие ответы, нужно использовать специальный объект - XMLHttpRequest:

var x = new XMLHttpRequest();

Смоделируем ситуацию асинхронного запроса

Для моделирования асинхронности используем таймер - наиболее простой и наглядный способ:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>асинхронные запросы</title>
		</head>
		<body>
		
		<h1>CallBack - смотри консоль</h1>
		<button id="b1">неудача</button>
		<button id="b2">успешно</button>
		
		<script>
			console.clear()
			
			/* здесь объявляется первая функция, которая терпит неудачу */
			function Outer1(){
				var result;
				setTimeout(function(){
					result = 545;
					console.log(result);
				}, 3000);
				return result;
			}
			
			document.querySelector('#b1').addEventListener('click', function(){
				/* вызов первой функции */
				console.log( Outer1() );
			});
			
			/* здесь объявляется вторая функция, которая выполняется успешно */
			function Outer2(whatDo) {
				var result;
				setTimeout(function(){
					result = 545;
					whatDo(result);
				}, 3000);
			}
			
			document.querySelector('#b2').addEventListener('click', function(){
				/* вызов второй функции */
				Outer2( function(x) {console.log(x)} );
			});
		</script>
		
		</body>
	</html>

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

Функция обратного вызова, указанная внутри таймера доступна только внутри Outer1(), если требуется получить к ней доступ, то используется функция Outer2(), которая принимает аргумент do, она описана в коде примера.


Демонстрация XMLHttpRequest

В следующем примере рассмотрим рабочий код программной отправки запросов и обработки ответов с использованием объекта XMLHttpRequest:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>Демонстрация XMLHttpRequest</title>
		</head>
		<body>
		
		<h1>Нажать сюда!</h1>
		
		<script>
			console.clear();
			/* Объявляем объект для AJAX */
			var xhr = new XMLHttpRequest();
			
			/* Объявляем функцию */
			function Outer3(o, whatDo){
				xhr.open('GET', 'http://nostroma.online/examples/date.php', true);
				xhr.onload = function(e){
					if(this.status == 200){
						whatDo(o, JSON.parse(this.responseText));
					};
				};
				xhr.send();
			};
			
			/* Вызываем объявленную функцию */
			document.querySelector('h1').addEventListener('click', function(e){
				this.style.color = 'red';
			
			/* Передаём CallBack в эту функцию, которая сама зависит от CallBack */
			Outer3(this, function(o, x){
					o.textContent = x.date1 + '->' + x.date2;
					o.style.color = 'black';
				});
			});

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

Следующий код асинхронного запроса посылает запрос на сервер каждую секунду и отображает часы сервера в реальном времени:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>Демонстрация XMLHttpRequest - время сервера</title>
		</head>
		<body>
		
		<script>
		
			/* Запрос данных */
			function showServerTime(){
				var xhr = new XMLHttpRequest();
				xhr.onreadystatechange = function(){
					if(xhr.readyState != 4) {return;};
					var spanTime = document.querySelector('#spanTime');
					spanTime.textContent = xhr.responseText;
				};
				xhr.open("GET", "http://nostroma.online/examples/server_time.php", true);
				xhr.send(null);
			};
			
			/* Автозапуск */
			window.onload = function(){
				setInterval("showServerTime()", 1000);
			};
			
		</script>
		
		<p>Сейчас на сервере:</p>
		
		<p id="spanTime"></p>
		
		</body>
	</html>
Показать в браузере (откроется в новой вкладке)

Асинхронная передача данных на сервер

Если с помощью AJAX можно получать данные с сервера, то, как вы уже догадались, их можно также и передавать. Это реализуется следующим JavaScript кодом - для метода передачи данных POST:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>
			Передача данных на сервер при помощи JavaScript: метод POST
			</title>
		</head>
		<body>
		
		<h1>Передача данных на сервер при помощи JavaScript: метод POST</h1>
		
		<!-- Данные, отправляемые на сервер, будем брать из двух полей ввода,
		при нажатии на кнопку "отправить" -->
		
		<input type="text" id="txt1" /><br />
		<input type="text" id="txt2" /><br />
		<input type="button" onclick="snd()" value="Отправить" /><br />
		
		
		<!-- Сюда, для примера, будут тут же возвращаться данные, 
		переданные на сервер -->
		<span>Данные, полученные с сервера: </span><br /><div></div>
		
		<script>
			function snd(){
				/* Получаем данные из полей ввода */
				var t1 = document.querySelector("#txt1").value;
				var t2 = document.querySelector("#txt2").value;
				
				/* Создаём объект XMLHttpRequest */
				var request = new XMLHttpRequest();
				
				/* Эта функция будет получать данные с сервера и записывать
				их в наш DIV */
				function reqReadyStateChange(){
					if(request.readyState == 4 && request.status == 200){
						document.querySelector("div").innerHTML=request.responseText;
					}
				}
				
				/* Готовим строку, которая будет отправлена на сервер,
				обратите внимание на формат строки! */
				var str = "text1=" + t1 + "&text2=" + t2;
				
				/* Открываем соединение и отсылаем данные на сервер */
				request.open("POST", "http://localhost/data/test2.php", true);
				request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
				request.onreadystatechange = reqReadyStateChange;
				request.send(str);
			}
		</script>
		
		</body>
	</html>

Важное замечание: чтобы передать данные на сервер в том же формате, что и HTML-формы, нужно указать соответствующий заголовок - xhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');

В request.open("POST", "http://localhost/data/test2.php"); нужно указать метод передачи данных (в этом случае "POST") и адрес документа, куда они будут отправлены.

Серверная сторона - документ по адресу http://localhost/data/test2.php должен принять данные и что-то с ними сделать, например, записать в базу данных, либо просто вернуть. Вот пример, когда сервер просто вернёт их бумерангом, ничего не делая (это уже язык php):

<?php
var_dump($_POST);
?>

А вот пример, когда сервер запишет эти данные в базу, где они будут храниться (это уже php, MySQL и язык запросов SQL):

<?php
if(isset($_POST['text1']) && !empty($_POST['text1'])
 && isset($_POST['text2']) && !empty($_POST['text2'])){
   $text1 = $_POST['text1'];
   $text2 = $_POST['text2'];
   
   $pdo = new PDO('mysql:host=localhost;dbname=name', 'login', 'password');
   $sql = "CREATE TABLE IF NOT EXISTS texts(
							id INTEGER PRIMARY KEY AUTO_INCREMENT,
							t1 TEXT,
							t2 TEXT)";
	
   $sql = "INSERT INTO texts(t1, t2) VALUES('$text1', '$text2')";
   $st = $pdo->exec($sql);
 }
?>

Ну вот как-то так, правда перед этим базу ещё надо создать, что-то вроде CREATE DATABASE [IF NOT EXISTS] db_name [CHARACTER SET charset] [COLLATE collation];, однако это выходит за рамки этого курса, об мы поговорим в соответствующих курсах сайта. Сейчас просто посмотрите на пример кода php, который создаёт базу данных:

<?php
$servername = "localhost";
$username = "username";
$password = "password";

// Create connection
$conn = new mysqli($servername, $username, $password);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error());
} 

// Create database
$sql = "CREATE DATABASE test";
if (mysqli_query($conn, $sql)) {
    echo "Database created successfully";
} else {
    echo "Error creating database: " . mysqli_error($conn);
}

mysqli_close($conn);
?>

Хотя метод POST более надёжный и безопасный, метод GET является более простым и быстрым способом передачи данных на сервер посредством AJAX. Конечно, длинные строки этим методом передать невозможно (предел у GET запроса 2000 символов), однако в большинстве случаев требуется отправить немного данных, например, проверить, находится ли пользователь онлайн (открыта ли у него на компьютере страница). Рассмотрим пример передачи данных методом GET:

<!DOCTYPE html>
	<html>
		<head>
			<meta charset="utf-8">
			<title>
				Передача данных на сервер при помощи JavaScript: метод GET
			</title>
		</head>
		<body>
		<!-- Это первый файл test.php -->
		
			<h1>Передача данных на сервер при помощи JavaScript: метод GET</h1>
			
			<!-- В этот DIV для примера данные, переданные методом GET будут
			тут же возвращаться -->
			<div></div>
			
			<script>
				/* Создаём объект XMLHttpRequest */
				var request = new XMLHttpRequest();
				
				/* Эта функция будет получать данные с сервера и записывать
				их в наш DIV */
				request.onreadystatechange = function(){
					if(request.readyState == 4 && request.status == 200){
						document.querySelector("div").innerHTML = request.responseText;
					}
				}
				
				/* Открываем соединение и отсылаем данные на сервер */
				request.open("GET", "http://localhost/data/test2.php?user=online", true);
				request.send();
			</script>
		
		</body>
	</html>

Если требуется передать две и более пар значений, то они должны быть разделены амперсандом (&), например, http://localhost/test.php?x=1&y=5&z=yes

Для того, чтобы периодически проверять на сервере открыта ли страница у пользователя, все, что находится между тегами <script></script> в примере нужно описать внутри функции, а затем вызывать эту функцию через нужный интервал времени.

Так же, как и в примере с методом POST, документ по адресу http://localhost/data/test2.php должен принять данные и как то их обработать. Ну, самый простой способ, для примера - это просто вернуть эти данные бумерангом:

<?php
var_dump($_GET);
?>

Комментарии

Введите Ваше имя:*

Введите e-mail:

Ваш комментарий:*

* Обязательные поля