Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 11.04.2015, 12:45
Аспирант
Отправить личное сообщение для 1lider Посмотреть профиль Найти все сообщения от 1lider
 
Регистрация: 12.04.2013
Сообщений: 86

Поправить XMLHttpRequest
Привет. Решил отказаться от jquery.ajax() и начеркать что-нибудь своё. Вот что получилось:
var _Request = function(options) {
    options = {
        type: options.type.toUpperCase() || 'POST',
        url: options.url || '',
        dataType: options.dataType.toUpperCase() || 'HTML',
        param: options.param || '',
        success: options.success || function(){},
        error: options.error || function(){}
    }
    var xhr;
    var rand = Math.floor(Math.random( )*(9999999+1));
    if(window.XMLHttpRequest) {
        try { xhr = new XMLHttpRequest(); }
        catch (e){}
    } else if (window.ActiveXObject) {
        try { xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
        catch(e) {}
        try { xhr = new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
        catch(e) {}
        try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }
        catch(e) {}
        try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
        catch(e) {}
    }
    if(options.type == "GET") {
        xhr.open(options.type, options.url+'?'+options.param+'&rnd='+rand, true);
    } else if(options.type == "POST") {
        xhr.open(options.type, options.url, true);
    } else { return; }
    if(options.dataType == 'HTML') {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
    } else if(options.dataType == 'JSON') {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
    } else { return; }
    xhr.setRequestHeader('Cache-Control', 'no-cache');
    xhr.onreadystatechange = function() {
        if(xhr.readyState == 4) {
            if(xhr.status == 200) {
                if(options.dataType == 'HTML') {
                    return options.success(xhr.responseText);
                } else if(options.dataType == 'JSON') {
                    var data = JSON.parse(xhr.responseText);
                    if(data != '' && data.length > 0) {
                        return options.success(data);
                    } else {
                        return options.error('error');
                    }
                }
            } else {
                return options.error('error');
            }
        } else {
            return options.error('error');
        }
    }
    if(options.type == "GET") {
        xhr.send(null);
    } else if(options.type == "POST") {
        xhr.send(options.param+'&rnd='+rand);
    } else { return; }
}

ИСПОЛЬЗОВАНИЕ:
_Request({
    type: 'GET',
    dataType: 'JSON',
    url: '/script.php',
    param: 'user=stashappy',
    success: function(data) {
        alert(data.result);
    }, error: function(data) {
        alert('ERROR');
    }
});

В принципе всё работает отлично, за исключением одного момента. Не хватает более правильной обработки ошибок, в случаях, когда php-файл-обработчик отсутствует на сервере или когда обработчик возвращает пустой результат. Запрос к следующему файлу, вызовет синтаксическую ошибку в JS коде:
script.php
<?php
exit;
?>

Прошу вашей помощи по решению данной задачи. Также хотелось бы узнать, могу ли я использовать в данном варианте событие abort(), для отмены запроса. Если нет, то как можно доработать данный JS код? Пример:
// примерно таким образом
var query = _Request({
// бла бла бла
});
query.abort(); // отменяем запрос
Ответить с цитированием
  #2 (permalink)  
Старый 11.04.2015, 13:02
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от theKingOfJava
 
Регистрация: 31.03.2015
Сообщений: 113

Сообщение от 1lider
отменяем запрос
Что значит отменяем? Как ты можешь отменить его, если он уже сделан?
Ответить с цитированием
  #3 (permalink)  
Старый 11.04.2015, 13:07
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

if(!!data) { ... }

if(data != '' && data.length > 0) - а если так 2 или более пробелов в ответе сервера значит ОК? И это проверяется после JSON.parse.
try {
    var data = JSON.parse(xhr.responseText)
} catch (e) {
    //ошибка формата
}

Последний раз редактировалось laimas, 11.04.2015 в 13:13.
Ответить с цитированием
  #4 (permalink)  
Старый 11.04.2015, 13:25
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от theKingOfJava Посмотреть сообщение
Что значит отменяем? Как ты можешь отменить его, если он уже сделан?
Метода .abort() обрывает текущий запрос. В IE вызов abort() не обрывает соединение, а оставлять его в подвешенном состоянии на некоторый таймаут (20-30 секунд).

Лимит на соединения не более 2 одновременных соединений с одним доменом-портом. Если два соединения уже висят по таймаут, то третье открыто не будет, пока одно из них не умрет.
Ответить с цитированием
  #5 (permalink)  
Старый 11.04.2015, 13:54
Аспирант
Отправить личное сообщение для 1lider Посмотреть профиль Найти все сообщения от 1lider
 
Регистрация: 12.04.2013
Сообщений: 86

Сообщение от laimas
if(data != '' && data.length > 0) - а если так 2 или более пробелов в ответе сервера значит ОК? И это проверяется после JSON.parse.
Можно убрать пробелы при проверке и сделать так:
if(xhr.responseText.replace(/\s+/g, '') != '' && xhr.responseText.replace(/\s+/g, '').length > 0) {
	try {
		var data = JSON.parse(xhr.responseText);
		return options.success(data);
	} catch (e) {
		return options.error('error');
	}
} else {
	return options.error('error');
}


По поводу события abort().
// примерно таким образом
var query = _Request({
	// бла бла бла
});
query.abort(); // отменяем запрос

Могу ли я провернуть подобное используя свой код? Вопрос возник, потому что объект xhr объявляется внутри функции _Request(), которая помещается в переменную query. Можем ли мы в данном случае применить query.abort();, чтобы добраться до объекта xhr и отменить тем самым запрос?
Ответить с цитированием
  #6 (permalink)  
Старый 11.04.2015, 16:40
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

if(xhr.responseText.replace(/\s+/g, '') != '' && xhr.responseText.replace(/\s+/g, '').length > 0) - это то зачем?

Можем ли мы в данном случае применить query.abort()

А попробуйте в своем случае.

А вообще, может задаться вопросом, а с какой целью требуется прерывать соединение? Судя по коду вы хотите и древних IE, но тогда надо учесть и их поведение.

Здесь в учебнике не нашел описания проблем (может и не там искал), но в сети много, например здесь.

Ну и тогда уж погружайтесь в ООП.
Ответить с цитированием
  #7 (permalink)  
Старый 12.04.2015, 08:17
Аспирант
Отправить личное сообщение для 1lider Посмотреть профиль Найти все сообщения от 1lider
 
Регистрация: 12.04.2013
Сообщений: 86

Цитата:
А попробуйте в своем случае.
Попробовал. Я так и предполагал, что в данном случае это не даст результата. Потому что событие abort() необходимо применить непосредственно к созданному нами объекту XHR. А мы его применяем к функции _Request(). Как реорганизовать данный программный код так, чтобы query.abort() отменял наш открытый запрос xhr.open() ?
Ответить с цитированием
  #8 (permalink)  
Старый 12.04.2015, 08:30
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Как реорганизовать данный программный код так

Либо начните с этого, либо объявляйте объект глобально.

А вообще, может лучше таймаут задавать свой, по истечении которого браузер сам закроет соединение. Ну не ради же интереса вам нужен abort().
Ответить с цитированием
  #9 (permalink)  
Старый 12.04.2015, 09:05
Аспирант
Отправить личное сообщение для 1lider Посмотреть профиль Найти все сообщения от 1lider
 
Регистрация: 12.04.2013
Сообщений: 86

Сообщение от laimas
ибо начните с этого,
Попробую начать с этого.
Сообщение от laimas
Ну не ради же интереса вам нужен abort()
На примере сайта OZON.RU. Если в поиске начать вводить ключевое слово ПУШКИН, то под строкой поиска, по мере написания этого слова, будет неоднократно всплывать окошко с предварительными результатами поиска. То же самое происходит и в поисковиках, когда в строку поиска, начинаешь вводить какое-либо ключевое слово и при этом, снизу выпадает список возможных вариантов. У себя сделал что-то подобное.

Задача: по мере того, как пользователь будет вводить ключевое слово в строку поиска, нужно отменять старые ajax запросы к серверу и формировать новый, на основе которого и выводить выпадающий список возможных вариантов поиска.

Для этого я и пытаюсь добавить событие abort(). Чтобы иметь возможность отменить ещё невыполненный запрос с ключевым словом "ПУШ", и сформировать новый запрос с ключевым словом "ПУШК", если пользователь дописал в строку поиска букву "К".
Ответить с цитированием
  #10 (permalink)  
Старый 12.04.2015, 10:05
Аспирант
Отправить личное сообщение для 1lider Посмотреть профиль Найти все сообщения от 1lider
 
Регистрация: 12.04.2013
Сообщений: 86

Всё оказалось очень просто. Немного подумав пришёл к выводу, что надо было просто добавить return xhr; сразу после открытия нашего запроса. Вот так:
function _Request(options) {
	options = {
		type: options.type.toUpperCase() || 'POST',
		url: options.url || '',
		dataType: options.dataType.toUpperCase() || 'HTML',
		param: options.param || '',
		success: options.success || function(){},
		error: options.error || function(){}
	}
	var xhr = false;
	var rand = Math.floor(Math.random( )*(9999999+1));
	if(window.XMLHttpRequest) {
        try { xhr = new XMLHttpRequest(); }
		catch (e) {}
    } else if (window.ActiveXObject) {
		try { xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
		catch(e) {}
		try { xhr = new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
		catch(e) {}
		try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }
		catch(e) {}
		try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
		catch(e) {}
	}
	if(xhr) {
		if(options.url != '') {
			if(options.type == "GET") {
				xhr.open(options.type, options.url+'?'+options.param+'&rnd='+rand, true);
			} else if(options.type == "POST") {
				xhr.open(options.type, options.url, true);
			} else {
				return options.error('error');
			}
		} else {
			return options.error('error');
		}
		xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
		xhr.setRequestHeader('Cache-Control', 'no-cache');
		xhr.onreadystatechange = function() {
			if(xhr.readyState == 4) {
				if(xhr.status == 200) {
					if(options.dataType == 'HTML') {
						return options.success(xhr.responseText);
					} else if(options.dataType == 'JSON') {
							if(xhr.responseText.replace(/\s+/g, '').length > 0) {
								try {
									var data = JSON.parse(xhr.responseText);
									return options.success(data);
								} catch (e) {
									return options.error('error');
								}
							} else {
								return options.error('error');
							}
					} else {
						return;
					}
				} else {
					return options.error('error');
				}
			} else {
				return options.error('error');		
			}
		}
		if(options.type == "GET") {
			xhr.send(null);
			return xhr; // ЗДЕСЬ
		} else if(options.type == "POST") {
			xhr.send(options.param+'&rnd='+rand);
			return xhr; // И ЗДЕСЬ
		} else {
			return options.error('error');
		}
	} else {
		return options.error('error');
	}
}

Использование:
var query = _Request({
    type: 'GET',
    dataType: 'JSON',
    url: '/script.php',
    param: 'user=stashappy',
    success: function(data) {
        alert(data.result);
    }, error: function(data) {
        alert('ERROR');
    }
});

Отмена запроса:
query.abort();
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
XMLHttpRequest передача массива серверу JaneLane AJAX и COMET 5 16.05.2014 12:09
запрос на другой сайт XMLHttpRequest vscorpion Internet Explorer 9 24.12.2013 16:46
xmlHttpRequest подскажите czp AJAX и COMET 4 10.12.2012 23:23
XMLHttpRequest status=0, хотя запрос проходит. arigasa AJAX и COMET 4 15.02.2011 20:14
Создание и уничтожение XMLHttpRequest Vlas AJAX и COMET 9 22.05.2009 12:38