[js] function makeRequest(url) { var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari, ... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { http_request.overrideMimeType('text/xml'); } } else if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } if (!http_request) { alert('Не вышло. Невозможно создать экземпляр класса XMLHTTP '); return false; } http_request.onreadystatechange = function() { alertContents(http_request); }; http_request.open('GET', 'my_game.php', true); http_request.send('slovo=1'); } function alertContents(http_request) { if (http_request.readyState == 4) { if (http_request.status == 200) { alert(http_request.responseText); } else { alert('С запросом возникла проблема.'); } } } [/js] Утащил с ajaxa.net как передалть, что бы он тупо обрабатывал POST запросы к файлу my_game.php и выдовал ответ.. пример: на 1 странице форма, я ввожу туда слово, скрипт POST посылает его файлу my_game.php? он его обрабатывает, типа проверка что такое слово еще не использованно и т.д.. если все оки, возвращает ответ "все ок", и эта фраза появляется на странице и.т...
Опять инглишь ((( dAllonE, спасибо, попробую понять.. а русские есть? с полной докой ка и что.. желательно что бы скачать можно было
Nemo а поменять в 35-й строке GET на POST религия не позволяет? Сходите сюда что-ли, вроде там относительно понятно написано. Читать "Способы общения с сервером-XMLHTTPRequest" и "Форматы данных для AJAX".
Nemo JsHttpRequest НО учти, это именно AJAX - framework, в отличие от jQuery, в котором еще куча всего есть
Nemo Статьи на javascript.ru читали? Попробуйте еще раз Если не получится, вечером попробую всё разжувать.
АJAX - Это всего лишь объект, с кучкой методов и свойств. Если понимать хоть как-то ООП, то сложности в понимания аякса не возникнет.
Короче толкователь из меня хреновый, но всё же пример: Файл test.php PHP: <?php // тут происходит обработка запроса, пришедшего от клиента, ну например поиск в базе if(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { // эта штука выставляется при помощи setRequestHeader в js // тупо выводим то, что нам прислал js if($_SERVER['REQUEST_METHOD']=='GET') echo $_GET['value']; else echo $_POST['value']; exit; } ?> Немного измененная (из соображений удобства) функция makeRequest: [js]function makeRequest(/* адрес скрипта-обработчика запроса */url, /* метод (get || post) */method, /* строка параметров (var1=1&var2=2&var3=3...) */params, /* функция-обработчик ответа */callback) { var http_request = false; // Сначала нам нужен какой-нибудь http-транспорт if(window.XMLHttpRequest) { // работаем через объект XMLHttpRequest (Mozilla, Opera, Safari, IE7 и выше) http_request = new XMLHttpRequest(); if(http_request.overrideMimeType) { // это для старых версий FF http_request.overrideMimeType('text/xml'); } } else if(window.ActiveXObject) { // Ослик, юзаем ActiveX try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { } } } if(!http_request) { // Попался какой-то древний браузер alert('Не вышло. Невозможно создать экземпляр класса XMLHTTP '); return false; } /* onreadystatechange - это событие объекта XMLHttpRequest, которое возникает каждый раз при изменении статуса текущего запроса Передаем туда свой обработчик как замыкание через функцию-обертку */ http_request.onreadystatechange = function(){ callback(http_request) } // дописываем наши параметры в строку запроса if(method=='get') url += (url.match(/\?/) ? '&' : '?') + params; http_request.open(method, url, true); // открываем соединение // указываем дополнительный заголовок, по которому будем затем отделять AJAX-запросы от обычных http_request.setRequestHeader('X-Requested-With', 'Simple Ajax'); // чтоб все было по правилам if(method=='post') http_request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // говорим, что хотели бы видеть в ответе сервера http_request.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*'); // если данные отправляются POST'ом, то строка параметров передается именно сюда // в случае GET тут должен быть null http_request.send(method=='post' ? params : null); } [/js] Небольшой кусок html: HTML: <!-- сюда будем выводить отладочные данные --> <div id="debug"></div> <input type="text" value="" id="some_field" /><input type="button" value="test" onclick="run_test()" /> Ну и обработка: [js]var debug_layer = document.getElementById('debug'); /* Это - обработчик ответа сервера, единственным аргументом принимает объект соединения Следует помнить, что этот обработчик будет вызван несколько раз - при изменении свойства readyState этого объекта по достижении значения 4 запрос считается выполненнным и мы можем посмотреть, что же нам вернул сервер в свойстве responseText при использовании XML в качестве формата данных ответное XML-дерево будет находиться в свойстве responseXML при использовании JSON достаточно заeval'ить текстовый ответ (и не забыть передать с сервера Content-Type: text/javascript) */ function result_handler(xmlhttp) { debug_layer.innerHTML += xmlhttp.readyState+'<br>'; if(xmlhttp.readyState==4) debug_layer.innerHTML += xmlhttp.responseText+'<br>'; } function run_test() { /* Нажатие кнопки вызовет посыл двух запросов GET'ом и POST'ом параметром value передается значение поля some_field */ makeRequest('test.php', 'get', 'value='+encodeURIComponent(document.getElementById('some_field').value), result_handler); makeRequest('test.php', 'post', 'value='+encodeURIComponent(document.getElementById('some_field').value), result_handler); } [/js] В принципе все, собираем пример (это все можно сделать в одном файле) и тыкаем кнопочку, периодически поглядывая в firebug и на слой debug. Думаю для просветления достаточно будет пары минут ЗЫ. (с умным видом) Kreker AJAX - это не объект, это технология. Ну и ООП тут особо не нужно (достаточно уровня "знаю, что такое точка"), лучше пусть поймет замыкания, модель событий и асинхронность в js.
Ивашка Как насчет ? Я пока никак не могу обойти этот баг. Пробовал и контроль запросов делать (чтобы не накладывались друг на друга) и проверку существования свойства XMLHttpRequest.status... Все равно ошибка выпадает. Примерно 1 раз за 20 запросов.
По идее status доступен только после того, как readyState установится в 4. До этого момента обращение к данному свойству не имеет смысла. Если всё же это вылезает при readyState==4 то скорее всего это баг FF, попробую поискать в багтрекере.
Kreker В багзилле вроде нету, но у меня есть идея (хотя без вашего кода сложно судить). Очень может быть, что объект транспорта у вас глобальный (как если бы в примере функции makeRequest мы забыли написать var 6-й строке). Следовательно при попытке выполнения двух и более запросов одновременно произошел бы конфликт между транспортами, что и приводит в итоге к такой ошибке. Это можно увидеть только если callback второго запроса начинает выполняться до того, как были приняты данные от первого, либо когда первый запрос проходит успешно, но сборщик мусора успевает уничтожить объект транспорта перед вызовом второго обработчика. Короче, код в студию!
Ивашка Я тоже так предполагаю. Вообще гуглил на эту тему. На phpforum.ru был топик по этому поводу, там даже vasa_c отвечал. В списке багов мозиллы вроде бы есть упоминание об этой ошибки. Дело в том, что я пытался предотвратить отсылку данных до тех пор, пока не будут приняты другие. [js] function newContent(param) { //Обработка param qstring = param; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); request.param = param; if (typeof(request.permit) == "undefined") { request.permit = true; //Разрешение на передачу, если свойства не было } //Если разрешение на передачу есть - передаем if (request.permit == true) { request.onreadystatechange = processRequestChange; request.open("POST", "./main.php" , true); request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); request.send(qstring); request.permit = false; request.query = false; } else { request.query = true; //Если AJAX уже передает данные, то новые ставим в очередь. } } else if (window.ActiveXObject) { //для винды } function processRequestChange() { abortRequest = window.setTimeout("request.abort();", 10000); if (request.readyState == 4) { clearTimeout(abortRequest); //Вот это - попытка абортнуть запрос и вызвать его заново, если нет свойства readyState if (typeof(request.status) == "undefined" || typeof(request.status) != "number") { request.abort(); newContent(request.param); return false; } if (request.status == 200) { otvet = new String(request.responseText); request.permit = true; //Ставим разрешение на передачу следующих данных if (request.query == true) { //Если на очереди стоит запрос, то обрабатываем его newContent(request.param); } } } [/js] Кто-то писал, что нужно создавать каждый раз новый объект, кто-то то, что нужно делать проверку - не занят ли AJAX. Некоторые вообще на синхронный режим советуют перейти, но на нем тоже ошибка выпадает.
Kreker Попробуйте просто избавиться от глобальных переменных (request, qstring etc) и processRequestChange вызывать через враппер: [js]request.onreadystatechange = function(){ processRequestChange(request) }[/js] Уверен, все будет тип-топ. Объект-то у вас и так каждый раз новый создается, да вот занимает он уже существующий слот.
Ивашка Пробовал так, мне выдает request.state undefined в processRequestChange, хотя объект вроде бы передается нормально. Еще покапаюсь, спасибо за подсказки.
request в определении processRequestChange указать не забыли? ну и для чистоты кода можно убрать извращения со свойствами permit и query - если уж делать принудительный вызов по цепочке, то только при помощи очереди (FIFO). ЗЫ. Вообще какая-то странная ошибка. Я как ни извращался, не смог её добиться ни во второй ни в третьей лисичке
Ну и напоследок, мои пять копеек для работы с AJAX (AJAJ, если быть точным и без нескольких рюшечек): [js]function ajax(url, params, method, handler, async) { // адрес обработчика, по-умолчанию - текущая страница if(!url) url = document.location.protocol + '//' + document.location.hostname + document.location.pathname + document.location.search // функция-обработчик ответа handler = handler || function(){} var pick = function() { // возвращает доступный HTTP-транспорт var transports = [ function(){ return new XMLHttpRequest() }, function(){ return new ActiveXObject("Msxml2.XMLHTTP") }, function(){ return new ActiveXObject("Msxml3.XMLHTTP") }, function(){ return new ActiveXObject("Microsoft.XMLHTTP") } ], result for(var i=0,l=transports.length; i<l; i++) { try { result = transports() } catch(exc) { continue } break } return result } var provider = pick() var xmlhttp = provider var closure = function() { // замыкание, которое передается в onreadystatechange // либо запускается один раз при синхронном запросе // получает объект с тремя свойствами: handler({readyState: xmlhttp.readyState, statusCodexmlhttp.readyState==4) ? xmlhttp.status : null, responseJSxmlhttp.readyState==4 && xmlhttp.status==200) ? eval('('+xmlhttp.responseText+')') : null }) if(xmlhttp.readyState==4) xmlhttp = null } if(method=='get') url += (url.match(/\?/) ? '&' : '?') + params try { // ну тут уже все понятно provider.open(method, url, !!async) provider.onreadystatechange = closure if(method=='post') provider.setRequestHeader('Content-type', 'application/x-www-form-urlencoded') provider.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*') provider.setRequestHeader('Connection', 'close') provider.send(method=='post' ? params : null) if(!async) closure() // если синхронный запрос } catch(exc) { } return provider }[/js] Пример использования: [js]ajax(null, 'some_var=1', 'get', function(result){ console.log(result, 'get', 'async') }, true) ajax(null, 'some_var=1', 'post', function(result){ console.log(result, 'post', 'sync') }, false) ajax(null, 'some_var=1', 'post', function(result){ console.log(result, 'post', 'async') }, true) ajax(null, 'some_var=1', 'get', function(result){ console.log(result, 'get', 'sync') }, false)[/js] Работает везде и без ошибок. Используется только в общедоступных разделах сайтов и умещает всю нужную мне функциональность. Конечно можно еще запариться на старые версии FF и IE, но я не вижу в этом необходимости.
Ивашка Спасибо за примеры, но мне хочется свой код до ума довести, я же все-таки не готовый вариант искал. request.state в processRequestChange указал. Сейчас заметил, что Undefined не request.state, а abortRequest = setTimeout("request.abort();", 10000); Заметил следующие две вещи: 1) Аборт не работает - ФФ выдает в консоли ошибку, подобного вида, что я привел сначала. 2) Если функции передавать объект, то она принимает только уже заданные методы и свойства, а вот если внутри функции задать существующее свойство, но не заданное ранне, то выскакивает ошибка, что это свойство не определено. UPD: Пошаманил, вроде бы отпала ошибка. Теперь надо выявить, что именно заставляло её появляться. UPD 2: Да, Вы были правы - был виноват глобальный request.