Javascript свойство xmlhttprequest.onreadystatechange

Пример использования

В следующем примере мы рассмотрим с вами как с помощью метода setRequestHeader() задать значение заголовка Content-Type (определяет MIME тип ресурса) HTTP запроса и отправить простой текст на сервер методом POST.

function postTextMessage(url, data) {
	let xhr = new XMLHttpRequest(); // инициализируем переменную новым объектом XMLHttpRequest

	xhr.open("POST", url); // определяем параметры для запроса на определенный адрес
	xhr.setRequestHeader("Content-Type", "text/plain;charset=utf-8"); // задаем значение заголовка HTTP запроса (текстовые данные в кодировке UTF-8)
	xhr.send(data); // отправляем запрос на сервер (используем значение параметра в качестве тела запроса)
}

В следующем примере мы рассмотрим с вами как с помощью метода setRequestHeader() задать значение заголовка Content-Type HTTP запроса и отправить данные формы на сервер методом POST.


function postFormData(url, data, callback) {
	let xhr = new XMLHttpRequest(); // инициализируем переменную новым объектом XMLHttpRequest

	xhr.open("POST", url); // определяем параметры для запроса на определенный адрес
	xhr.onreadystatechange = function() { // обработчик событий, вызываемый при запуске события readystatechange (при каждом изменении свойства readyState)
		// проверяем состояние запроса, числовой код состояния HTTP ответа и наличие переданной функции
		if (this.readyState === 4 && this.status == 200 && callback) {
			callback(xhr); // вызываем переданную в качестве параметра функ­цию
		}
	}
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // задаем значение заголовка HTTP запроса (значения кодируются в кортежах с ключом, разделенных символом '&', с '=' между ключом и значением)
	xhr.send(data); // отправляем запрос на сервер (используем значение параметра в качестве тела запроса)
} 

В следующем примере мы рассмотрим с вами как с помощью метода setRequestHeader() задать значение заголовка Content-Type HTTP запроса и отправить данные в формате JSON на сервер методом POST.

function postJSONData(url, data, callback) {
	let xhr = new XMLHttpRequest(); // инициализируем переменную новым объектом XMLHttpRequest
	
	xhr.open("POST", url); // определяем параметры для запроса на определенный адрес
	xhr.onreadystatechange = function() { // обработчик событий, вызываемый при запуске события readystatechange (при каждом изменении свойства readyState)
		// проверяем состояние запроса, числовой код состояния HTTP ответа и наличие переданной функции
		if (this.readyState === 4 && this.status == 200 && callback) {
			callback(xhr); // вызываем переданную в качестве параметра функ­цию
		}
	}
	xhr.setRequestHeader("Content-Type", "application/json"); // задаем значение заголовка HTTP запроса (данные в формате JSON)
	xhr.send(data); // отправляем запрос на сервер (используем значение параметра в качестве тела запроса)
}

JavaScript XMLHttpRequest

Пример 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."!";
}     
?>

§Streaming Data with XHR

In some cases an application may need or want to process a stream of
data incrementally: upload the data to the server as it becomes available
on the client, or process the downloaded data as it arrives from the
server. Unfortunately, while this is an important use case, today there
is no simple, efficient, cross-browser API for XHR streaming:

  • The send method expects the full payload in case of
    uploads.

  • The response, responseText, and
    responseXML attributes are not designed for streaming.

Streaming has never been an official use case within the official XHR
specification. As a result, short of manually splitting an upload into
smaller, individual XHRs, there is no API for streaming data from client
to server. Similarly, while the XHR2 specification does provide some
ability to read a partial response from the server, the implementation is
inefficient and very limited. That’s the bad news.

The good news is that there is hope on the horizon! Lack of streaming
support as a first-class use case for XHR is a well-recognized
limitation, and there is work in progress to address the problem:

The combination of XHR and Streams API will enable efficient XHR
streaming in the browser. However, the Streams API is still under active
discussion, and is not yet available in any browser. So, with that, we’re
stuck, right? Well, not quite. As we noted earlier, streaming uploads
with XHR is not an option, but we do have limited support for streaming
downloads with XHR:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/stream');
xhr.seenBytes = 0;

xhr.onreadystatechange = function() { 
  if(xhr.readyState > 2) {
    var newData = xhr.responseText.substr(xhr.seenBytes); 
    // process newData

    xhr.seenBytes = xhr.responseText.length; 
  }
};

xhr.send();
  1. Subscribe to state and progress notifications

  2. Extract new data from partial response

  3. Update processed byte offset

This example will work in most modern browsers. However, performance
is not great, and there are a large number of implementation caveats and
gotchas:

  • Note that we are manually tracking the offset for seen bytes and
    then manually slicing the data: responseText is buffering
    the full response! For small transfers, this may not be an issue, but
    for larger downloads, and especially on memory-constrained devices
    such as mobile handsets, this is a problem. The only way to release
    the buffered response is to finish the request and open a new one.

  • Partial response can be read only from the responseText
    attribute, which limits us to text-only transfers. There is no way to
    read partial response of a binary transfer.

  • Once partial data is read, we must identify message boundaries:
    application logic must define its own data format and then buffer and
    parse the stream to extract individual messages.

  • Browsers differ in how they buffer received data: some browsers
    may release data immediately, while others may buffer small responses
    and release them in larger chunks.

  • Browsers differ in which content-types they allow to be read
    incrementally—e.g., some allow «text/html,» while others will only
    work with «application/x-javascript.»

In short, currently, XHR streaming is neither efficient nor
convenient, and to make matters worse, the lack of a common specification
also means that the implementations differ from browser to browser. As a
result, at least until the Streams API is available, XHR is not a good
fit for streaming.

No need to despair! While XHR may not meet the criteria, we do have
other transports that are optimized for the streaming use case:
Server-Sent Events offers a convenient API for streaming text-based
data from server to client, and WebSocket offers efficient,
bidirectional streaming for both binary and text-based data.

Отправляем данные на сервер

Обыч­но, что­бы отпра­вить дан­ные на сер­вер, нуж­но делать запрос. Вы нажи­ма­е­те кноп­ку на стра­ни­це, бра­у­зер ухо­дит думать, ждёт отве­та сер­ве­ра и рису­ет вам новую стра­ни­цу в соот­вет­ствии с этим отве­том. Гру­бо гово­ря, запрос на сер­вер застав­ля­ет вашу стра­ни­цу перезагружаться.

К сча­стью, инже­не­ры дав­но при­ду­ма­ли, как отправ­лять дан­ные на сер­вер, не пере­за­гру­жая стра­ни­цу. Для это­го исполь­зу­ют JavaScript.

Что­бы отпра­вить запрос, нам пона­до­бит­ся встро­ен­ный объ­ект XMLHttpRequest(). Вот как мы вво­дим его в повествование:

// создаём новый экземпляр запроса XHRlet xhr = new XMLHttpRequest();

Для запро­са нам нуж­но знать адрес, куда будем отправ­лять наш JSON — это и есть адрес наше­го скрип­та, кото­рый мы напи­шем поз­же. Мы будем писать его на PHP, поэто­му зара­нее можем при­ду­мать ему имя и адрес, где он будет лежать: http://mihailmaximov.ru/projects/json/json.php.

// адрес, куда мы отправим нашу JSON-строкуurl = «http://mihailmaximov.ru/projects/json/json.php»;

Когда мы зна­ем адрес, мы можем открыть соеди­не­ние, что­бы сер­вер был готов при­нять наши дан­ные. Это зна­чит, что мы пока ниче­го цен­но­го туда не посы­ла­ем, а про­сто пре­ду­пре­жда­ем сер­вер, что ско­ро что-то прилетит:

// открываем соединение. url — это переменная с нашим адресомxhr.open(«POST», url, true);

Теперь напи­шем заго­ло­вок запро­са, что­бы сер­вер пони­мал, какие дан­ные мы ему при­шлём и как ему их обра­ба­ты­вать. Так как у нас JSON, то это и про­пи­шем в заголовке:

 // устанавливаем заголовок — выбираем тип контента, который отправится на сервер, в нашем случае мы явно пишем, что это JSONsetRequestHeader(«Content-Type», «application/json»);

Чуть ниже сра­зу про­пи­шем пове­де­ние скрип­та на слу­чай отве­та сер­ве­ра. Сер­вер дол­жен обра­бо­тать наши дан­ные, вер­нуть ответ, а мы долж­ны этот ответ пой­мать и выве­сти на страницу:

Послед­нее, что нам оста­лось сде­лать, — выта­щить наши вве­дён­ные дан­ные из полей, собрать из них JSON и отпра­вить на сервер:

 // преобразуем наши данные JSON в строку      var data = JSON.stringify({ «name»: name.value, «lastname»: lastname.value });      // когда всё готово, отправляем JSON на сервер      xhr.send(data);

Готовый скрипт на странице

Использование XMLHTTPRequest

Различают два использования XmlHttpRequest. Первое — самое простое, синхронное.

Синхронный XMLHttpRequest

В этом примере через XMLHTTPRequest с сервера запрашивается страница http://example.org/, и текст ответа сервера показывается через alert().

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', false);
xmlhttp.send(null);
if(xmlhttp.status == 200) {
  alert(xmlhttp.responseText);
}

Здесь сначала создается запрос, задается открытие () синхронного соединение с адресом /xhr/test.html и запрос отсылается с null,
т.е без данных.

При синхронном запросе браузер «подвисает» и ждет на строчке 3, пока сервер не ответит на запрос. Когда ответ получен — выполняется строка 4, код ответа сравнивается с 200 (ОК), и при помощи alert
печатается текст ответа сервера. Все максимально просто.

Свойство responseText получит такой же текст страницы, как браузер, если бы Вы в перешли на /xhr/test.html. Для сервера
GET-запрос через XmlHttpRequest ничем не отличается от обычного перехода на страницу.

Асинхронный XMLHttpRequest

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

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', true);
xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4) {
     if(xmlhttp.status == 200) {
       alert(xmlhttp.responseText);
         }
  }
};
xmlhttp.send(null);

Асинхронность включается третьим параметром функции open. В отличие от синхронного запроса, функция send() не останавливает
выполнение скрипта, а просто отправляет запрос.

Запрос xmlhttp регулярно отчитывается о своем состоянии через вызов функции xmlhttp.onreadystatechange. Состояние под номером 4 означает конец выполнения, поэтому функция-обработчик
при каждом вызове проверяет — не настало ли это состояние.

Вообще, список состояний readyState такой:

  • 0 — Unitialized
  • 1 —
  • 2 — Loaded
  • 3 — Interactive
  • 4 — Complete

Состояния 0-2 вообще не используются.

Вызов функции с состоянием Interactive в теории должен происходить каждый раз при получении очередной порции данных от сервера.
Это могло бы быть удобным для обработки ответа по частям, но Internet Explorer не дает доступа к уже полученной части ответа.

Firefox дает такой доступ, но для обработки запроса по частям состояние Interactive все равно неудобно из-за сложностей обнаружения ошибок соединения.
Поэтому Interactive тоже не используется.

На практике используется только последнее, Complete.

Если хотите углубиться в тонкости багов браузеров c readyState, отличными от 4, то многие из них рассмотрены в статье на.

Не используйте синхронные запросы

Синхронные запросы применяются только в крайнем случае, когда кровь из носу необходимо дождаться ответа сервера до продолжения скрипта. В 999 случаях из 1000
можно использовать асинхронные запросы. При этом общий алгоритм такой:

  1. Делаем асинхронный запрос
  2. Рисуем анимированную картинку или просто запись типа «Loading…»
  3. В onreadystatechange при достижении состояния 4 убираем Loading и, в зависимости от status вызываем обработку ответа или ошибки.

Кроме того, иногда полезно ставить ограничение на время запроса. Например, хочется генерировать ошибку, если запрос висит более 10 секунд.

Для этого сразу после send() через setTimeout ставится вызов обработчика ошибки, который очищается при получении ответа и обрывает запрос с генерацией ошибки,
если истекли 10 секунд.

Таймаут на синхронный запрос ставить нельзя, браузер может висеть долго-долго.. А вот на асинхронный — пожалуйста.

Этот пример демонстрирует такой таймаут.

var xmlhttp = getXmlHttp()
xmlhttp.open("POST", "/someurl", true);
xmlhttp.onreadystatechange=function(){
  if (xmlhttp.readyState != 4) return
  clearTimeout(timeout) // очистить таймаут при наступлении readyState 4
  if (xmlhttp.status == 200) {
      // Все ок
      ...
      alert(xmlhttp.responseText);
      ...
  } else {
      handleError(xmlhttp.statusText) // вызвать обработчик ошибки с текстом ответа
  }
}
xmlhttp.send("a=5&b=4");
// Таймаут 10 секунд
var timeout = setTimeout( function(){ xmlhttp.abort(); handleError("Time over") }, 10000);
function handleError(message) {
  // обработчик ошибки
  ...
  alert("Ошибка: "+message)
  ...
}

Ограничения безопасности. Кросс-доменный XMLHttpRequest

Для ограничения XmlHttpRequest используется философия «Same Origin Policy». Она очень проста — каждый сайт в своей песочнице. Запрос можно делать только на адреса
с тем же протоколом, доменом, портом, что и текущая страница.

Т.е, со страницы на адресе http://site.com нельзя сделать XmlHttpRequest на адрес https://site.com, http://site.com:81 или http://othersite.com

Это создает проблему, если хочется взять контент с другого сайта. Как правило, в этом случае вместо XmlHttpRequest используются другие средства, например, загрузка через
динамически создаваемый тег

Проксирование

Самый простой способ обойти это ограничение — проксирование. Допустим, мы хотим сделать запрос с http://site.com на http://remote.com/get.html.

Чтобы обойти ограничение, вместо указания remote.com в методе open(), там ставится специальный URL вида http://site.com/proxy/remote.com/get.html. Так что запрос приходит на наш веб-сервер, который проксирует его на сервер site.com, который в свою очередь обрабатывает этот запрос, как нужно.

Если remote.com находится на другом сервере, то серверу site.com придется проксировать посетителю как запрос, так и ответ. При этом, разумеется, никак не будут задействованы куки remote.com, так что не получится отдельной авторизации, учета пользователей или чтото в этом роде с отдельными куками.

Проксирование настраивается соответствующим модулем (mod_proxy, proxy module и т.п.) веб-сервера для всех адресов, начинающихся на /proxy.

Например, при использовании web-сервера Apache, для проксирования нужны директивы ProxyPass, ProxyPassReverse. Кроме того, доступны еще модули, которые по необходимости правят урлы, разархивируют контент

Использование наддомена

Часто кроссбраузерные запросы — это

  1. Способ обойти ограничения в 2 одновременных соединения к одному домену-порту.
  2. Способ использовать два разных сервера в общении с посетителем. Например, на chat.site.ru — чат-демон, на www.site.ru — веб-сервер.

Кросс-доменные запросы с поддомена типа http://a.site.com, http://b.site.com на базовый домен site.com допустимы при использовании свойства document.domain, которое надо установить в site.com

// на странице a.site.com
...
document.domain='site.com'
...
// все, теперь могу делать XmlHttpRequest на site.com
xmlhttp.open(..'http://site.com/feedme.php'..)

Запрос на старый домен

В браузере Internet Explorer, чтобы сделать запрос на старый домен a.site.com, нужно вернуть свойство document.domain обратно. В остальных браузерах это приводит к ошибке, поэтому можно оформить код типа такого:

var oldDomain = document.domain
document.domain = "site.com"
try {
    // для IE, в остальных браузерах ошибка...
    document.domain = oldDomain;
} catch(e) {  /* ... но в них все и так работает */ }
//... работаем с a.site.com ...

Same origin и фреймы

Приятным бонусом свойства document.domain является возможность коммуникации между фреймами/ифреймами на одном домене.

То есть, например, если

  • во фрейме с адреса http://a.site.com установлен document.domain=’site.com’,
  • на фрейме с адреса http://b.site.com установлен домен document.domain=’site.com’
  • на фрейме с адреса http://site.com установлен (обязательно!) домен document.domain=’site.com’

То эти три фрейма могут свободно общаться посредством javascript и XmlHttpRequest.

Обычно такая коммуникация используется при создании чатов/событий с сервера, когда на site.com находится основной веб-сервер, а на chat.site.com висит чат-демон.

Internet Explorer trusted zone

Любые запросы допустимы между сайтами, находящимися в доверенной (trusted) зоне Internet Explorer. Так что, внутренний корпоративный портал может быть у всех пользователей в этой зоне, и он сможет делать запросы к любым сайтам.

XhrIframeProxy

Еще один хитрый подход называется , и позволяет делать XmlHttpRequest к любым доменам при помощи хитрого iframe-хака. Он основан на том, что фреймы с разных доменов могут читать и менять друг у друга anchor, т.е часть адреса после решетки ‘#’. За счет этого организуется специальный протокол, по которому «проксируется» XmlHttpRequest.

Этот метод, в принципе, вполне жизнеспособен, особенно для небольшого объема данных.

Кросс-доменные запросы в FF3/IE8/Opera9..

В спецификации HTML 5 предусмотрены кросс-доменные запросы .

Создатели Firefox и Opera реализовали этот вариант, см. например MDC: .

Разработчики IE8 пошли другим путем и предлагают .

Оба способа вполне жизнеспособны и уже пригодны для использования в интранет-приложениях, когда на всех машинах администратор ставит одинаковый браузер, например, Firefox 3 ?

Synchronous requests

If in the method the third parameter is set to , the request is made synchronously.

In other words, JavaScript execution pauses at and resumes when the response is received. Somewhat like or commands.

Here’s the rewritten example, the 3rd parameter of is :

It might look good, but synchronous calls are used rarely, because they block in-page JavaScript till the loading is complete. In some browsers it becomes impossible to scroll. If a synchronous call takes too much time, the browser may suggest to close the “hanging” webpage.

Many advanced capabilities of , like requesting from another domain or specifying a timeout, are unavailable for synchronous requests. Also, as you can see, no progress indication.

Because of all that, synchronous requests are used very sparingly, almost never. We won’t talk about them any more.

GET и POST-запросы. Кодировка.

Во время обычного submit’а формы браузер сам кодирует значения полей и составляет тело GET/POST-запроса для посылки на сервер. При работе через XmlHttpRequest, это нужно делать самим, в javascript-коде. Большинство проблем и вопросов здесь связано с непониманием, где и какое кодирование нужно осуществлять.

Вначале рассмотрим общее кодирование запросов, ниже — правильную работу с русским языком для windows-1251.

Существуют два вида кодирования HTTP-запроса. Основной — urlencoded, он же — стандартное кодирование URL. Пробел представляется как %20, русские буквы и большинство спецсимволов кодируются, английские буквы и дефис оставляются как есть.

Способ, которым следует кодировать данные формы при submit’е, задается в ее HTML-таге:

<form method="get"> // метод GET с кодировкой по умолчанию
<form method="post" enctype="application/x-www-form-urlencoded"> // enctype явно задает кодировку
<form method="post"> // метод POST с кодировкой по умолчанию (urlencoded, как и предыдущая форма)

Если форма submit’ится обычным образом, то браузер сам кодирует (urlencode) название и значение каждого поля данных ( и т.п.) и отсылает форму на сервер в закодированном виде.

Формируя XmlHttpRequest, мы должны формировать запрос «руками», кодируя поля функцией .

Конечно, пропускать через encodeURIComponent стоит только те переменные, в которых могут быть спецсимволы или не английские буквы, т.е которые и будут как раз закодированы.

Например, для посылки GET-запроса с произвольными параметрами name и surname, их необходимо закодировать вот так:

// Пример с GET
...
var params = 'name=' + encodeURIComponent(name) + '&surname=' + encodeURIComponent(surname)
xmlhttp.open("GET", '/script.html?'+params, true)
...
xmlhttp.send(null)

В методе POST параметры передаются не в URL, а в теле, посылаемом через . Поэтому нужно указывать не в адресе, а при вызове

Кроме того, при POST обязателен заголовок Content-Type, содержащий кодировку. Это указание для сервера — как обрабатывать (раскодировать) пришедший запрос.

// Пример с POST
...
var params = 'name=' + encodeURIComponent(name) + '&surname=' + encodeURIComponent(surname)
xmlhttp.open("POST", '/script.html', true)
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
...
xmlhttp.send(params)

Заголовки Content-Length, Connection в POST-запросах, хотя их и содержат некоторые «руководства», обычно не нужны. Используйте их, только если Вы действительно знаете, что делаете.

Запросы multipart/form-data

Второй способ кодирования — это отсутствие кодирования. Например, кодировать не нужно для пересылки файлов. Он указывается в форме (только для POST) так:

<form method="post" enctype="multipart/form-data">

В этом случае при отправке данных на сервер ничего не кодируется. А сервер, со своей стороны, посмотрев на Content-Type(=multipart/form-data), поймет, что пришло.

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

Кодировка (языковая)

Если Вы используете только UTF-8 — пропустите эту секцию.

Все идущие на сервер параметры GET/POST, кроме случая multipart/form-data, кодируются в UTF-8. Не в кодировке страницы, а именно в UTF-8. Поэтому, например, в PHP их нужно при необходимости перекодировать функцией iconv.

<?php
// ajax.php
$name = iconv('UTF8','CP1251',$_GET);
?>

С другой стороны, ответ с сервера браузер воспринимает именно в той кодировке, которая указана в заголовке ответа Content-Type. Т.е, опять же, в PHP, чтобы браузер воспринял ответ в windows-1251 и нормально отобразил данные на странице в windows-1251,
нужно послать заголовок с кодировкой в php-коде, например так:

<?php
// ajax.php
header('Content-Type: text/plain; charset=utf-8');
?>

Или же, такой заголовок должен добавить сервер. Например, в apache автоматически добавляется кодировка опцией:

# в конфиге апача
AddDefaultCharset windows-1251

JSON Example

This example reads a menu from myTutorials.txt, and displays the menu in a web
page:

JSON Example

<div id=»id01″></div><script>var xmlhttp = new XMLHttpRequest();
var url = «myTutorials.txt»;xmlhttp.onreadystatechange = function()
{    if (this.readyState == 4 && this.status ==
200) {        var myArr = JSON.parse(this.responseText);       
myFunction(myArr);    }};xmlhttp.open(«GET», url, true);
xmlhttp.send();function myFunction(arr) {    var
out = «»;    var i;    for(i = 0; i <
arr.length; i++) {        out += ‘<a
href=»‘ + arr.url + ‘»>’ +        
arr.display + ‘</a><br>’;    }   
document.getElementById(«id01»).innerHTML = out;}
</script>

Добавить комментарий

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

Adblock
detector