Создание удобного обработчика AJAX-запросов

от автора

Многие сталкивались с проблемой огромного количества post и get запросов по ходу разработки сайта. В частности, в разработке на jQuery, где не один запросик-стучалка, а куча запросов в тех-же самых магазинах: корзина, избранное, фильтр. Да что я распыляюсь. Все и так прекрасно понимают прелести разработки больших проектов.

Вроде бы оно и быстро реализовано на JQ… но как-то не очень. Все равно тратятся драгоценные символы и время на создание удобного кода.

Столкнувшись с этой проблемой в 105 раз, решил — хватит. Пора что-то менять. И поменял.

Суть приёма такая:
Для обработки запросов используем один файл с классом-обработчиком. Он принимает запросы и роутит их на соответствующий метод объекта обработчика. Чтобы не заморачиваться долго, было решено и коллбэк выводить обязательно ( см. функцию retJSON) из свойства объекта CLBK.
Соответственно, отправление/получение происходит также с помощью одного метода. В параметры JS-метода включается отдельно название метода и отдельно — все остальное.

Данный способ позволил мне:
1. Избавиться от тучи файлов-обработчиков.
2. Хоть как-то привести код в порядок, вместо обыкновенного JQ-бедлама.
3. Создать определённую структуру кода и даже возможность расширения приложения.
4. Повысить читаемость кода. Будучи программистом культурным («Господи Иисусе!», — возопят знатоки предмета. — «ты же совсем не понимаешь принципов программирования, какая тут культура.» Может быть где-то недочитал матчасть, но плевать я хотел на ихнее мнение, если честно. Мне так комфортно ) в последнее время стал задумываться и о людях, которые после меня будут разбираться в моих строчках. Посему потратил пару дополнительных часов.

Имхо, данное решение множество раз уже было воссоздано во фреймворках разного толка и сорта. Однако приятно иметь своё собственное решение. И пользоваться им.

Ниже скрипты и пример использования обработчика.

var JQ = $; var Core = {          rmvFrmBskt: function(id){ 	 		this.request(arguments.callee,{ID:id},function(data){ 			 			if(data.status === "OK") 				Core.getBskt(); 		}) 	},  	request:function(method,params,callback_fnc){ 		 		if(	 			( 				typeof method !== 'string'&& 				typeof method !== "function" 			)|| 			typeof params !== "object"|| 			params === null 		) 		throw "Core.request::Arguments isn't valid"; 		 		if(typeof method !== 'string') 			method = Hlp.getMthName(this,method); 		 		if(method==='') throw "Core.request:: method is hollow"; 		JQ.post("/callback.php",{"method":method,"params":params},function(data,callback){ 		 			try{var JSONobj = JSON.parse(data)} 			catch(e){ 				throw(e); 			} 			if(JSONobj.error){ 				throw "Core.request:: " + JSONobj.error; 			} 			 			if(JSONobj.notify_text){ 				 				alert(JSONobj.notify_text); 				throw "Core.request:: " + JSONobj.notify_text; 			} 			 			if(JSONobj.echo){ 				if(Util.bid("debugdiv")) 				Util.rmv(Util.bid("debugdiv")); 				var dbg = Util.crt("div","debugdiv"); 				body.appendChild(dbg); 				dbg.innerHTML = JSONobj.echo; 			} 			callback_fnc(JSONobj); 		}); 	}   var Hlp = {      getMthName:function(obj,mth) { 		var mthName = '';         for (var i in obj) { 			if(obj[i]===mth){ 				mthName =  i; 				break; 			} 		}; 		return mthName;     } }   var Util = { 	bid: function(id){ 		if(!!id){ 			return document.getElementById(id); 		} 	}, 	rmv: function(Node){ 		Node.parentNode.removeChild(Node, Node.parentNode); 	}, 	rmvAllCh: function(Node){ 		var cnt = Node.children.length; 		 		for(var k = 0; k < cnt; k++){ 		 			Util.rmv(Node.children[0]); 		} 	}, 	bc: function(className){ 	 		var Node = document.getElementsByClassName(className); 		 		if(Node.length==1){ 			 			return Node[0]; 		}else{ 			return Node; 		} 	}, 	crt: function(Node, className, attr){ 		var tmp = document.createElement(Node);  		if((typeof className === 'string')&&(className!='')){ 		 			tmp.className = className; 		} 		 		if(typeof attr === 'object'&&attr != null){ 			for(var i in attr){ 			 				tmp[i] = attr[i]; 			} 		} 		return tmp; 	}  } 

Немного PHP

class CallBack{ 	 	public static $CLBK = Array(); 	 	static function router(){ 		 		if(	!CModule::IncludeModule("catalog")|| 			!CModule::IncludeModule("sale")|| 			!CModule::IncludeModule("iblock")){ 			 				CallBack::retJson(Array("error"=>"PHP CModule isn't included")); 				die(); 			} 	 		if(isset($_REQUEST)&&!empty($_REQUEST)&&method_exists("CallBack", $_REQUEST['method']."Clbk")){ 		 			$methodName = $_REQUEST['method']."Clbk"; 			CallBack::$methodName($_REQUEST['params']); 		}else{ 			CallBack::retJson(Array("error"=>"PHP Callback.router::invalid arguments")); 		} 	} 	 	static function retJson(){ 	 		if(!is_array(self::$CLBK)) die(); 		 		echo json_encode(self::$CLBK); 	}  public function rmvFrmBsktClbk($PARAMS){ 	 		CSaleBasket::Delete((int)$PARAMS['ID']); 		self::$CLBK['status'] = "OK"; 	} }   CallBack::router(); CallBack::retJson(); 

Как могут заметить знающие программисты, решение написано для 1С-Битрикс. Да, знаю, где-то там в дебрях документации есть строки о встроенных AJAX-утилитах Битрикса. Но написать свой обработчик и знать как он работает, это как создать первую программу хелло ворлд. Каждый должен создать велосипед, ибо тогда не программист.

ссылка на оригинал статьи http://habrahabr.ru/post/233965/


Комментарии

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

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