aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/guide/ajax/с_чего_начать/index.html
blob: e06b408228dc0ed0b77d77142f26d7f22b61179e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
---
title: С чего начать
slug: Web/Guide/AJAX/С_чего_начать
tags:
  - AJAX
translation_of: Web/Guide/AJAX/Getting_Started
---
<p> </p>

<p>В этой статье рассмотрены основные принципы работы AJAX и даны два простых примера, использующих эту технологию.</p>

<h3 id=".D0.A7.D1.82.D0.BE_.D1.82.D0.B0.D0.BA.D0.BE.D0.B5_AJAX.3F" name=".D0.A7.D1.82.D0.BE_.D1.82.D0.B0.D0.BA.D0.BE.D0.B5_AJAX.3F">Что такое AJAX?</h3>

<p>Ajax означает Асинхронный JavaScript и XML. В основе технологии лежит использование нестандартного объекта <code><a href="/ru/XMLHttpRequest" title="ru/XMLHttpRequest">XMLHttpRequest</a></code>, необходимого для взаимодействия со скриптами на стороне сервера. Объект может как отправлять, так и получать информацию в различных форматах включая XML, HTML и даже текстовые файлы. Самое привлекательное в Ajax — это его асинхронный принцип работы. С помощью этой технологии можно осуществлять взаимодействие с сервером без необходимости перезагрузки страницы. Это позволяет обновлять содержимое страницы частично, в зависимости от действий пользователя.</p>

<p>Две особенности, которые мы рассмотрим:</p>

<ul>
 <li>Отправление запросов серверу без перезагрузки страницы</li>
 <li>Работа с XML документами</li>
</ul>

<h3 id=".D0.A8.D0.B0.D0.B3_1.C2.A0.E2.80.94_.D0.9A.D0.B0.D0.BA_.D0.BF.D0.BE.D1.81.D0.BB.D0.B0.D1.82.D1.8C_HTTP_.D0.B7.D0.B0.D0.BF.D1.80.D0.BE.D1.81" name=".D0.A8.D0.B0.D0.B3_1.C2.A0.E2.80.94_.D0.9A.D0.B0.D0.BA_.D0.BF.D0.BE.D1.81.D0.BB.D0.B0.D1.82.D1.8C_HTTP_.D0.B7.D0.B0.D0.BF.D1.80.D0.BE.D1.81">Шаг 1 — Как послать HTTP запрос</h3>

<p>Для того, чтобы послать HTTP запрос на сервер используя JavaScript, вам необходим экземпляр класса, который позволит это сделать. Такой класс впервые был введен в Internet Explorer как объект ActiveX, называемый <code>XMLHTTP</code>. Позже в Mozilla, Safari и другие браузеры был введен класс <code>XMLHttpRequest</code>, который поддерживал методы и свойства изначального объекта ActiveX от Microsoft.</p>

<p>В результате, чтобы создать кросс-браузерный объект требуемого класса, вы можете сделать следующее:</p>

<pre>var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
    httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
</pre>

<p>(В целях наглядности, код выше является немного упрощенным. Более жизненный пример будет рассмотрен в шаге 3 этой статьи)</p>

<p>Некоторые версии некоторых броузеров Mozilla не будут корректно работать, если ответ сервера не содержит заголовка XML <code>mime-type</code>. Чтобы решить эту проблему, вы можете использовать вызовы дополнительных методов для переопределения заголовка полученного от сервера, если он отличен от <code>text/xml</code>.</p>

<pre>httpRequest = new XMLHttpRequest();
httpRequest.overrideMimeType('text/xml');
</pre>

<p>Далее вам необходимо решить, что вы будете делать после получения ответа сервера. На этом этапе вам необходимо указать объекту, какая JavaScript функция будет обрабатывать ответ. Это делается путем присваивания свойству <code>onreadystatechange</code> имени JavaScript функции, которую вы собираетесь использовать:</p>

<p><code>httpRequest.onreadystatechange = nameOfTheFunction;</code></p>

<p>Заметьте, что после названия функции нет скобок и не указано параметров, потому что вы просто присваиваете ссылку на функцию, а не вызываете ее. К тому же, вместо указания имени функции, вы можете использовать возможность JavaScript объявлять функции на лету (так называемые «анонимные функции») и указывать действия, которые тотчас же будут обрабатывать ответ:</p>

<pre>httpRequest.onreadystatechange = function(){
    // какой-нибудь код
};
</pre>

<p>Далее, после того как вы объявили что будет происходить после получения ответа, вам необходимо сделать запрос. Вы должны вызвать методы класса <code>open()</code> и <code>send()</code>:</p>

<pre>httpRequest.open('GET', 'http://www.example.org/some.file', true);
httpRequest.send(null);
</pre>

<ul>
 <li>Первый параметр вызова функции <code>open()</code> — метод HTTP запроса (GET, POST, HEAD или любой другой метод, который вы хотите использовать). Используйте методы в соответствии с HTTP стандартами, иначе некоторые браузеры (такие как Firefox) могут не обработать запрос. Информация о допустимых HTTP запросах доступна по адресу <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">спецификации W3C</a></li>
 <li>Второй параметр — URL запрашиваемой страницы. Из соображений безопасности возможность запрашивать страницы сторонних доменов недоступна. Убедитесь, что вы используете одинаковое доменное имя на всех страницах, иначе вы получите ошибку 'доступ запрещен' при вызове функции <code>open()</code>. Типичной ошибкой при доступе к сайту через <code>site.ru</code> является отправка запроса на <code>www.site.ru</code>.</li>
 <li>Третий параметр указывает, является ли запрос асинхронным. Если он <code>TRUE</code>, то выполнение JavaScript продолжится во время ожидания ответа сервера. В этом и заключается асинхронность технологии.</li>
</ul>

<p>Параметром метода <code>send()</code> могут быть любые данные, которые вы хотите послать на сервер. Данные должны быть сформированы в строку запроса:</p>

<p><code>name=value&amp;anothername=othervalue&amp;so=on</code></p>

<p>Заметьте, что если вы хотите отправить данные методом <code>POST</code>, вы должны изменить MIME-тип запроса с помощью следующей строки:</p>

<pre>httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
</pre>

<p>Иначе сервер проигнорирует данные отправленные методом POST.</p>

<h3 id=".D0.A8.D0.B0.D0.B3_2.C2.A0.E2.80.94_.D0.9E.D0.B1.D1.80.D0.B0.D0.B1.D0.B0.D1.82.D1.8B.D0.B2.D0.B0.D0.B5.D0.BC_.D0.BE.D1.82.D0.B2.D0.B5.D1.82_.D1.81.D0.B5.D1.80.D0.B2.D0.B5.D1.80.D0.B0" name=".D0.A8.D0.B0.D0.B3_2.C2.A0.E2.80.94_.D0.9E.D0.B1.D1.80.D0.B0.D0.B1.D0.B0.D1.82.D1.8B.D0.B2.D0.B0.D0.B5.D0.BC_.D0.BE.D1.82.D0.B2.D0.B5.D1.82_.D1.81.D0.B5.D1.80.D0.B2.D0.B5.D1.80.D0.B0">Шаг 2 — Обрабатываем ответ сервера</h3>

<p>Отправляя запрос, вы указали имя функции JavaScript, обрабатывающей ответ.</p>

<p><code>httpRequest.onreadystatechange = nameOfTheFunction;</code></p>

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

<pre>if (httpRequest.readyState == 4) {
    // все в порядке, ответ получен
} else {
    // все еще не готово
}
</pre>

<p>Полный список значений кодов <code>readyState</code> такой:</p>

<ul>
 <li>0 (uninitialized)</li>
 <li>1 (loading)</li>
 <li>2 (loaded)</li>
 <li>3 (interactive)</li>
 <li>4 (complete)</li>
</ul>

<p>(<a class="external" href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp">Источник</a>)</p>

<p>Следующее, что нужно проверить — это статус HTTP-ответа. Все возможные коды можно посмотреть на <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">сайте W3C</a>. Для наших целей нам интересен только код ответа <code>200 OK</code>.</p>

<pre>if (httpRequest.status == 200) {
    // великолепно!
} else {
    // с запросом возникли проблемы,
    // например, ответ может быть 404 (Не найдено)
    // или 500 (Внутренняя ошибка сервера)
}
</pre>

<p>Теперь, после проверки состояния запроса и статуса HTTP-ответа, вы можете делать с данными, полученными от сервера, все что угодно. Есть два способа получить доступ к данным:</p>

<ul>
 <li><code>httpRequest.responseText</code> – возвращает ответ сервера в виде строки текста.</li>
 <li><code>httpRequest.responseXML</code> – возвращает ответ сервера в виде объекта <code>XMLDocument</code>, который вы можете обходить используя функции JavaScript DOM</li>
</ul>

<h3 id=".D0.A8.D0.B0.D0.B3_3.C2.A0.E2.80.94_.D0.9F.D1.80.D0.BE.D1.81.D1.82.D0.BE.D0.B9_.D0.BF.D1.80.D0.B8.D0.BC.D0.B5.D1.80" name=".D0.A8.D0.B0.D0.B3_3.C2.A0.E2.80.94_.D0.9F.D1.80.D0.BE.D1.81.D1.82.D0.BE.D0.B9_.D0.BF.D1.80.D0.B8.D0.BC.D0.B5.D1.80">Шаг 3 — Простой пример</h3>

<p>Давайте соберем все вместе и сделаем простой пример HTTP-запроса. Наш JavaScript запросит HTML документ <code>test.html</code>, который содержит текст "I'm a test." и выведет содержимое файла в диалоговом окне.</p>

<pre>&lt;script type="text/javascript" language="javascript"&gt;
    function makeRequest(url) {
        var httpRequest = false;

        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            httpRequest = new XMLHttpRequest();
            if (httpRequest.overrideMimeType) {
                httpRequest.overrideMimeType('text/xml');
                // Читайте ниже об этой строке
            }
        } else if (window.ActiveXObject) { // IE
            try {
                httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {}
            }
        }

        if (!httpRequest) {
            alert('Не вышло :( Невозможно создать экземпляр класса XMLHTTP ');
            return false;
        }
        httpRequest.onreadystatechange = function() { alertContents(httpRequest); };
        httpRequest.open('GET', url, true);
        httpRequest.send(null);

    }

    function alertContents(httpRequest) {

        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                alert(httpRequest.responseText);
            } else {
                alert('С запросом возникла проблема.');
            }
        }

    }
&lt;/script&gt;
&lt;span
    style="cursor: pointer; text-decoration: underline"
    onclick="makeRequest('test.html')"&gt;
        Сделать запрос
&lt;/span&gt;
</pre>

<p><br>
 В этом примере:</p>

<ul>
 <li>Пользователь нажимает на ссылку "Сделать запрос" в броузере;</li>
 <li>Это вызывает функцию <code>makeRequest()</code> с параметром <code>test.html</code> — именем HTML файла;</li>
 <li>Посылается запрос, после чего (<code>onreadystatechange</code>) выполнение передается <code>alertContents()</code>;</li>
 <li><code>alertContents()</code> проверяет получен ли ответ и все ли с ним в порядке, после чего содержимое файла <code>test.html</code> выводится в диалоговом окне.</li>
</ul>

<p>Вы можете попробовать пример в действии <a class="external" href="http://www.akvi.ru/mozdev/httprequest_test.html" rel="follow">здесь</a>, а сам тестовый файл можно посмотреть <a class="external" href="http://www.akvi.ru/mozdev/test.html" rel="follow">здесь</a>.</p>

<p><strong>Замечание</strong>: Строка <code>httpRequest.overrideMimeType('text/xml');</code> вызовет ошибки в консоли JavaScript в Firefox 1.5 или более позднем, как описано в <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311724" rel="freelink">https://bugzilla.mozilla.org/show_bug.cgi?id=311724</a>, если страница вызванная с помощью XMLHttpRequest не является правильным XML (например, если это обычный текст). На самом деле это корректное поведение.</p>

<p><strong>Замечание 2</strong>: Если вы посылаете запрос не на статический XML-файл, а на серверный скрипт, возвращающий XML, то нужно установить некоторые заголовки ответа, если вы планируете сделать вашу страницу работоспособной в Internet Explorer помимо Mozilla. Если вы не установите заголовок <code>Content-Type: application/xml</code>, IE будет сообщать об ошибке JavaScript, 'Object Expected', после строки, где вы пытаетесь получить доступ к XML элементу. Если вы не установите заголовок <code>Cache-Control: no-cache</code> броузер будет кэшировать ответ и никогда не будет повторно отправлять запрос, что сделает отладку весьма «забавной».</p>

<p><strong>Замечание 3</strong>: Если переменная <code>httpRequest</code> используется глобально, то конкурирующие функции, вызывающие <code>makeRequest()</code> могут конкурировать друг с другом, вызывая состязания. Объявление переменной <code>httpRequest</code> локально в функции и передача ее в <code>alertContent()</code> предотвращает состязания.</p>

<p><strong>Замечание 4</strong>: При привязывании функции обратного вызова к <code>onreadystatechange</code> нельзя указывать аргументов. По этой причине не работает следующий код:</p>

<pre>httpRequest.onreadystatechange = alertContents(httpRequest); // (не работает)
</pre>

<p>Таким образом, для успешной регистрации функции, вы должны передать ей аргументы косвенно через анонимную функцию или используя <code>httpRequest</code> как глобальную переменную. Вот пример:</p>

<pre>httpRequest.onreadystatechange = function() { alertContents(httpRequest); };  //1 (одновременный запрос)
httpRequest.onreadystatechange = alertContents;  //2 (глобальная переменная)
</pre>

<p>Первый способ позволяет делать несколько запросов одновременно, а второй используется, когда переменная <code>httpRequest</code> является глобальной.</p>

<p><strong>Замечание 5</strong>: В случае ошибки взаимодействия (например, если сервер упал), при попытке доступа к переменной .status метода onreadystatechange будет сгенерировано исключение. Убедитесь, что if...then заключено в try...catch. (См. <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=238559" rel="freelink">https://bugzilla.mozilla.org/show_bug.cgi?id=238559</a>).</p>

<pre>function alertContents(httpRequest) {

        try {
            if (httpRequest.readyState == 4) {
                if (httpRequest.status == 200) {
                    alert(httpRequest.responseText);
                } else {
                    alert('С запросом возникла проблема.');
                }
            }
        }
        catch( e ) {
            alert('Произошло исключение: ' + e.description);
        }

    }
</pre>

<h3 id=".D0.A8.D0.B0.D0.B3_4.C2.A0.E2.80.94_.D0.A0.D0.B0.D0.B1.D0.BE.D1.82.D0.B0_.D1.81_XML_.D0.BE.D1.82.D0.B2.D0.B5.D1.82.D0.BE.D0.BC" name=".D0.A8.D0.B0.D0.B3_4.C2.A0.E2.80.94_.D0.A0.D0.B0.D0.B1.D0.BE.D1.82.D0.B0_.D1.81_XML_.D0.BE.D1.82.D0.B2.D0.B5.D1.82.D0.BE.D0.BC">Шаг 4 — Работа с XML ответом</h3>

<p>В предыдущем примере, после того как был получен ответ на HTTP-запрос мы использовали <code>responseText</code> запрашиваемого объекта, который содержал данные файла <code>test.html</code>. Теперь давайте попробуем использовать свойство <code>responseXML</code>.</p>

<p>Прежде всего, давайте создадим правильный XML документ, который мы будем запрашивать. Документ (<code>test.xml</code>) содержит следующее:</p>

<pre>&lt;?xml version="1.0" ?&gt;
&lt;root&gt;
    I'm a test.
&lt;/root&gt;
</pre>

<p>В скрипте нам всего лишь необходимо заменить строку запроса на:</p>

<pre>...
onclick="makeRequest('test.xml')"&gt;
...
</pre>

<p>Далее в <code>alertContents()</code> нам нужно заменить строку <code>alert(httpRequest.responseText);</code> на:</p>

<pre>var xmldoc = httpRequest.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
</pre>

<p>Этот код берет объект <code>XMLDocument</code>, возвращаемый <code>responseXML</code> и использует методы DOM для доступа к данным, содержащимся в документе XML. Посмотреть <code>test.xml</code> можно <a class="external" href="http://www.akvi.ru/mozdev/test.xml" rel="follow">здесь</a>, а обновленный скрипт <a class="external" href="http://www.akvi.ru/mozdev/httprequest_test_xml.html" rel="follow">здесь</a>.</p>

<p>Чтобы узнать больше о методах DOM, посмотрите <a class="external" href="http://www.mozilla.org/docs/dom/">реализация DOM в Mozilla</a>.</p>

<p>{{ languages( { "ca": "ca/AJAX/Primers_passos", "de": "de/AJAX/Getting_Started", "en": "en/AJAX/Getting_Started", "es": "es/AJAX/Primeros_Pasos", "fr": "fr/AJAX/Premiers_pas", "it": "it/AJAX/Iniziare", "ja": "ja/AJAX/Getting_Started", "ko": "ko/AJAX/Getting_Started", "pl": "pl/AJAX/Na_pocz\u0105tek", "pt": "pt/AJAX/Como_come\u00e7ar", "zh-cn": "cn/AJAX/\u5f00\u59cb" } ) }}</p>