За последние 24 часа нас посетили 17744 программиста и 1625 роботов. Сейчас ищут 1280 программистов ...

Дурацкий AJAX =( помогите :((

Тема в разделе "JavaScript и AJAX", создана пользователем EvelRus, 23 июн 2008.

  1. EvelRus

    EvelRus Активный пользователь

    С нами с:
    16 ноя 2006
    Сообщения:
    2.168
    Симпатии:
    0
    Адрес:
    Москва
    [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? он его обрабатывает, типа проверка что такое слово еще не использованно и т.д.. если все оки, возвращает ответ "все ок", и эта фраза появляется на странице и.т...
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    +1, фтопку его!
     
  3. dAllonE

    dAllonE Guest

    Nemo, если в лом разбираться с Ajax'om самостоятельно зайди сюда.
    Тут все просто :)
     
  4. EvelRus

    EvelRus Активный пользователь

    С нами с:
    16 ноя 2006
    Сообщения:
    2.168
    Симпатии:
    0
    Адрес:
    Москва
    Опять инглишь :((((

    dAllonE, спасибо, попробую понять.. а русские есть? с полной докой ка и что.. желательно что бы скачать можно было
     
  5. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Nemo а поменять в 35-й строке GET на POST религия не позволяет? :)
    Сходите сюда что-ли, вроде там относительно понятно написано. Читать "Способы общения с сервером-XMLHTTPRequest" и "Форматы данных для AJAX".
     
  6. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    Nemo

    JsHttpRequest

    НО учти, это именно AJAX - framework, в отличие от jQuery, в котором еще куча всего есть
     
  7. EvelRus

    EvelRus Активный пользователь

    С нами с:
    16 ноя 2006
    Сообщения:
    2.168
    Симпатии:
    0
    Адрес:
    Москва
    мне пример нужен :((((
    я так не понимаю :((

    С подробными коментариями...
     
  8. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Nemo
    Статьи на javascript.ru читали? Попробуйте еще раз ;) Если не получится, вечером попробую всё разжувать.
     
  9. dAllonE

    dAllonE Guest

    Хм... Ну немного на русском есть тут. Читать начиная со слов "AJAX – как много в этом звуке!"
     
  10. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    АJAX - Это всего лишь объект, с кучкой методов и свойств. Если понимать хоть как-то ООП, то сложности в понимания аякса не возникнет.
     
  11. EvelRus

    EvelRus Активный пользователь

    С нами с:
    16 ноя 2006
    Сообщения:
    2.168
    Симпатии:
    0
    Адрес:
    Москва
    мне решение нужно!!!!! А не что это такое!
    а ооп я терпеть не могу :)
     
  12. dAllonE

    dAllonE Guest

    *dAllonE обиделсо за ООП вздохнул и ушел домой...
     
  13. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Короче толкователь из меня хреновый, но всё же пример:
    Файл test.php
    PHP:
    1. <?php
    2.  
    3. // тут происходит обработка запроса, пришедшего от клиента, ну например поиск в базе
    4. if(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { // эта штука выставляется при помощи setRequestHeader в js
    5.   // тупо выводим то, что нам прислал js
    6.   if($_SERVER['REQUEST_METHOD']=='GET') echo $_GET['value'];
    7.   else echo $_POST['value'];
    8.   exit;
    9. }
    10.  
    11.  
    12. ?>
    Немного измененная (из соображений удобства) функция 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:
    1. <!-- сюда будем выводить отладочные данные -->
    2. <div id="debug"></div>
    3.  
    4. <input type="text" value="" id="some_field" /><input type="button" value="test" onclick="run_test()" />
    5.  
    Ну и обработка:
    [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.
     
  14. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Ивашка
    Как насчет
    ?
    Я пока никак не могу обойти этот баг. Пробовал и контроль запросов делать (чтобы не накладывались друг на друга) и проверку существования свойства XMLHttpRequest.status... Все равно ошибка выпадает. Примерно 1 раз за 20 запросов.
     
  15. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    По идее status доступен только после того, как readyState установится в 4. До этого момента обращение к данному свойству не имеет смысла.
    Если всё же это вылезает при readyState==4 то скорее всего это баг FF, попробую поискать в багтрекере.
     
  16. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Kreker
    В багзилле вроде нету, но у меня есть идея (хотя без вашего кода сложно судить). Очень может быть, что объект транспорта у вас глобальный (как если бы в примере функции makeRequest мы забыли написать var 6-й строке). Следовательно при попытке выполнения двух и более запросов одновременно произошел бы конфликт между транспортами, что и приводит в итоге к такой ошибке. Это можно увидеть только если callback второго запроса начинает выполняться до того, как были приняты данные от первого, либо когда первый запрос проходит успешно, но сборщик мусора успевает уничтожить объект транспорта перед вызовом второго обработчика.
    Короче, код в студию!
     
  17. S.t.A.M.

    S.t.A.M. Активный пользователь

    С нами с:
    10 сен 2007
    Сообщения:
    1.041
    Симпатии:
    0
  18. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Ивашка
    Я тоже так предполагаю. Вообще гуглил на эту тему. На 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. Некоторые вообще на синхронный режим советуют перейти, но на нем тоже ошибка выпадает.
     
  19. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Kreker
    Попробуйте просто избавиться от глобальных переменных (request, qstring etc) и processRequestChange вызывать через враппер:
    [js]request.onreadystatechange = function(){ processRequestChange(request) }[/js]
    Уверен, все будет тип-топ.
    Объект-то у вас и так каждый раз новый создается, да вот занимает он уже существующий слот.
     
  20. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Ивашка
    Пробовал так, мне выдает request.state undefined в processRequestChange, хотя объект вроде бы передается нормально. Еще покапаюсь, спасибо за подсказки.
     
  21. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    request в определении processRequestChange указать не забыли? ну и для чистоты кода можно убрать извращения со свойствами permit и query - если уж делать принудительный вызов по цепочке, то только при помощи очереди (FIFO).

    ЗЫ. Вообще какая-то странная ошибка. Я как ни извращался, не смог её добиться ни во второй ни в третьей лисичке :(
     
  22. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Ну и напоследок, мои пять копеек для работы с 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,
    statusCode:(xmlhttp.readyState==4) ? xmlhttp.status : null,
    responseJS:(xmlhttp.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, но я не вижу в этом необходимости.
     
  23. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Ивашка
    Спасибо за примеры, но мне хочется свой код до ума довести, я же все-таки не готовый вариант искал.

    request.state в processRequestChange указал. Сейчас заметил, что Undefined не request.state, а
    abortRequest = setTimeout("request.abort();", 10000);

    Заметил следующие две вещи:
    1) Аборт не работает - ФФ выдает в консоли ошибку, подобного вида, что я привел сначала.
    2) Если функции передавать объект, то она принимает только уже заданные методы и свойства, а вот если внутри функции задать существующее свойство, но не заданное ранне, то выскакивает ошибка, что это свойство не определено.

    UPD: Пошаманил, вроде бы отпала ошибка. Теперь надо выявить, что именно заставляло её появляться.
    UPD 2: Да, Вы были правы - был виноват глобальный request.