Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Ajax разбор метода (https://javascript.ru/forum/jquery/9496-ajax-razbor-metoda.html)

mycoding 20.05.2010 22:08

Ajax разбор метода
 
Приведу реализацию ajax в JQuery, извините что полностью, просто очень хочется понять как она у них сделана.
Обратим внимание на
function complete() {
			// Process result
			if ( s.complete ) {
				s.complete.call( callbackContext, xhr, status);
			}

			// The request was completed
			if ( s.global ) {
				trigger( "ajaxComplete", [xhr, s] );
			}

			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active ) {
				jQuery.event.trigger( "ajaxStop" );
			}
		}

Т.е. этот код запустится как только завершиться загрузка.
Можете, пожалуйста объяснить, что происходит внутри этого метода
ajax: function( origSettings ) {
		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
		
		var jsonp, status, data,
			callbackContext = origSettings && origSettings.context || s,
			type = s.type.toUpperCase();

		// convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Handle JSONP Parameter Callbacks
		if ( s.dataType === "jsonp" ) {
			if ( type === "GET" ) {
				if ( !jsre.test( s.url ) ) {
					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
				}
			} else if ( !s.data || !jsre.test(s.data) ) {
				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
			}
			s.dataType = "json";
		}

		// Build temporary JSONP function
		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
			jsonp = s.jsonpCallback || ("jsonp" + jsc++);

			// Replace the =? sequence both in the query string and the data
			if ( s.data ) {
				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
			}

			s.url = s.url.replace(jsre, "=" + jsonp + "$1");

			// We need to make sure
			// that a JSONP style response is executed properly
			s.dataType = "script";

			// Handle JSONP-style loading
			window[ jsonp ] = window[ jsonp ] || function( tmp ) {
				data = tmp;
				success();
				complete();
				// Garbage collect
				window[ jsonp ] = undefined;

				try {
					delete window[ jsonp ];
				} catch(e) {}

				if ( head ) {
					head.removeChild( script );
				}
			};
		}

		if ( s.dataType === "script" && s.cache === null ) {
			s.cache = false;
		}

		if ( s.cache === false && type === "GET" ) {
			var ts = now();

			// try replacing _= if it is there
			var ret = s.url.replace(rts, "$1_=" + ts + "$2");

			// if nothing was replaced, add timestamp to the end
			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
		}

		// If data is available, append data to url for get requests
		if ( s.data && type === "GET" ) {
			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
		}

		// Watch for a new set of requests
		if ( s.global && ! jQuery.active++ ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// Matches an absolute URL, and saves the domain
		var parts = rurl.exec( s.url ),
			remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);

		// If we're requesting a remote document
		// and trying to load JSON or Script with a GET
		if ( s.dataType === "script" && type === "GET" && remote ) {
			var head = document.getElementsByTagName("head")[0] || document.documentElement;
			var script = document.createElement("script");
			script.src = s.url;
			if ( s.scriptCharset ) {
				script.charset = s.scriptCharset;
			}

			// Handle Script loading
			if ( !jsonp ) {
				var done = false;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function() {
					if ( !done && (!this.readyState ||
							this.readyState === "loaded" || this.readyState === "complete") ) {
						done = true;
						success();
						complete();

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}
					}
				};
			}

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709 and #4378).
			head.insertBefore( script, head.firstChild );

			// We handle everything using the script element injection
			return undefined;
		}

		var requestDone = false;

		// Create the request object
		var xhr = s.xhr();

		if ( !xhr ) {
			return;
		}

		// Open the socket
		// Passing null username, generates a login popup on Opera (#2865)
		if ( s.username ) {
			xhr.open(type, s.url, s.async, s.username, s.password);
		} else {
			xhr.open(type, s.url, s.async);
		}

		// Need an extra try/catch for cross domain requests in Firefox 3
		try {
			// Set the correct header, if data is being sent
			if ( s.data || origSettings && origSettings.contentType ) {
				xhr.setRequestHeader("Content-Type", s.contentType);
			}

			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
			if ( s.ifModified ) {
				if ( jQuery.lastModified[s.url] ) {
					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
				}

				if ( jQuery.etag[s.url] ) {
					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
				}
			}

			// Set header so the called script knows that it's an XMLHttpRequest
			// Only send the header if it's not a remote XHR
			if ( !remote ) {
				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			}

			// Set the Accepts header for the server, depending on the dataType
			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
				s.accepts[ s.dataType ] + ", */*" :
				s.accepts._default );
		} catch(e) {}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active ) {
				jQuery.event.trigger( "ajaxStop" );
			}

			// close opended socket
			xhr.abort();
			return false;
		}

		if ( s.global ) {
			trigger("ajaxSend", [xhr, s]);
		}

		// Wait for a response to come back
		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
			// The request was aborted
			if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
				// Opera doesn't call onreadystatechange before this point
				// so we simulate the call
				if ( !requestDone ) {
					complete();
				}

				requestDone = true;
				if ( xhr ) {
					xhr.onreadystatechange = jQuery.noop;
				}

			// The transfer is complete and the data is available, or the request timed out
			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
				requestDone = true;
				xhr.onreadystatechange = jQuery.noop;

				status = isTimeout === "timeout" ?
					"timeout" :
					!jQuery.httpSuccess( xhr ) ?
						"error" :
						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
							"notmodified" :
							"success";

				var errMsg;

				if ( status === "success" ) {
					// Watch for, and catch, XML document parse errors
					try {
						// process the data (runs the xml through httpData regardless of callback)
						data = jQuery.httpData( xhr, s.dataType, s );
					} catch(err) {
						status = "parsererror";
						errMsg = err;
					}
				}

				// Make sure that the request was successful or notmodified
				if ( status === "success" || status === "notmodified" ) {
					// JSONP handles its own success callback
					if ( !jsonp ) {
						success();
					}
				} else {
					jQuery.handleError(s, xhr, status, errMsg);
				}

				// Fire the complete handlers
				complete();

				if ( isTimeout === "timeout" ) {
					xhr.abort();
				}

				// Stop memory leaks
				if ( s.async ) {
					xhr = null;
				}
			}
		};

		// Override the abort handler, if we can (IE doesn't allow it, but that's OK)
		// Opera doesn't fire onreadystatechange at all on abort
		try {
			var oldAbort = xhr.abort;
			xhr.abort = function() {
				if ( xhr ) {
					oldAbort.call( xhr );
				}

				onreadystatechange( "abort" );
			};
		} catch(e) { }

		// Timeout checker
		if ( s.async && s.timeout > 0 ) {
			setTimeout(function() {
				// Check to see if the request is still happening
				if ( xhr && !requestDone ) {
					onreadystatechange( "timeout" );
				}
			}, s.timeout);
		}

		// Send the data
		try {
			xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
		} catch(e) {
			jQuery.handleError(s, xhr, null, e);
			// Fire the complete handlers
			complete();
		}

		// firefox 1.5 doesn't fire statechange for sync requests
		if ( !s.async ) {
			onreadystatechange();
		}

		function success() {
			// If a local callback was specified, fire it and pass it the data
			if ( s.success ) {
				s.success.call( callbackContext, data, status, xhr );
			}

			// Fire the global callback
			if ( s.global ) {
				trigger( "ajaxSuccess", [xhr, s] );
			}
		}

		function complete() {
			// Process result
			if ( s.complete ) {
				s.complete.call( callbackContext, xhr, status);
			}

			// The request was completed
			if ( s.global ) {
				trigger( "ajaxComplete", [xhr, s] );
			}

			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active ) {
				jQuery.event.trigger( "ajaxStop" );
			}
		}
		
		function trigger(type, args) {
			(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
		}

		// return XMLHttpRequest to allow aborting the request etc.
		return xhr;
	},

Skipp 20.05.2010 22:13

Ты псих, иди в отпуск:)

И кстати, комментарии читал?:)

mycoding 20.05.2010 22:30

Просто пытаюсь сделать ajax метод в своём frameworke, до этого просто загружал данный в див.
А теперь появилась необходимость проверить данные на сервере, и чтобы сервер прислал ответ,
если ответ YES значит то..., если NO это

<button style="position:absolute;left50;top:500;" onclick="$.ajax({url:'index.php',complete:function(xhr){alert(xhr.responseText)}});">Нажать</button>

Skipp 20.05.2010 22:35

Ясн знач своё колесо строишь:)

так в чём же проблема? для этого есть специальные события. ждёшь ответ и всё. Ну а на сервере уже другая тема:)

mycoding 21.05.2010 08:10

То же самое но с синронным запросом делается легко, уже получилось.
Но на сайте http://xmlhttprequest.ru/ сказано, что пользоваться ассинхронным запросом не надо, вот и пробую по другому.

micscr 21.05.2010 08:49

Цитата:

Сообщение от mycoding (Сообщение 55867)
Просто пытаюсь сделать ajax метод в своём frameworke

А зачем ты вообще этим занимаешься? Это принесет денег?

Skipp 21.05.2010 09:16

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

Kolyaj 21.05.2010 09:17

Цитата:

Сообщение от micscr
А зачем ты вообще этим занимаешься? Это принесет денег?

А вы думаете Резиг, когда начал писать jQuery, считал, что она принесёт денег?

micscr 21.05.2010 09:45

Цитата:

Сообщение от Kolyaj (Сообщение 55906)
А вы думаете Резиг, когда начал писать jQuery, считал, что она принесёт денег?

эта ниша уже занята.

mycoding 21.05.2010 09:48

http://javascript.ru/blog/mycoding/Pishem-svoj-jquery
Это моя курсовая просто да и интересно тоже.

Kolyaj 21.05.2010 10:00

Цитата:

Сообщение от micscr
эта ниша уже занята.

Когда Гугл начинал, ниша поиска тоже была занята. Когда Яндекс начинал, она тоже была занята.

Мне вот интересно, почему на такие вещи все так реагируют, как будто их заставляют этот очередной велосипед использовать? Видишь недостатки -- покажи, достоинства -- похвали, не нужен он тебе -- ну иди мимо.

mycoding 21.05.2010 10:12

Вот, что получилось

Js.extend(Js,{
	ajax : function(param){					
				var xhr,
				url = param.url,
				method = param.method || 'GET',
				data = param.data || null,
				async = (param.async==undefined)?true:param.async,
				complete = param.complete;
				if(window.ActiveXObject){xhr=new ActiveXObject("Microsoft.XMLHTTP");}
				else if(window.XMLHttpRequest) {xhr=new XMLHttpRequest();}
				else {alert('Видимо в вашем браузере не поддреживается ajax');}
				xhr.onreadystatechange = function(){
					if(xhr.readyState != 4 || xhr.readyState==0){/*Loading*/;}
					if(xhr.readyState == 4){
						if(xhr.status == 200){/*Пришёл ответ*/if(complete){complete();}}
						else{elem.html("Error: returned status code " + xhr.status + " " + xhr.statusText);}
					}
				};
				if(method=='GET') {xhr.open(method, url, async);xhr.send(data);}
				else{
					xhr.open(method, url, async);
					xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					xhr.send(data);
				}
				return xhr;
			}
});

Я просто не пойму как же реализовать, чтобы можно было передать в этот запрос что делать когда всё загрузиться. Ведь надо будет получить
данные запроса, а как их получить если они внутри?
Их же надо прописать в вызываемой функции.
Т.е.
$.ajax({url:'index.php',complete:function(xhr){
         if(xhr.responseText=='YES'){alert('YES');}
         else if(xhr.responseText=='NO') {alert('NO');}
         else {alert('Какие-то не те данные');}
}};

Но вот как в JQuery передаётся информация внутрь функции я не пойму.

JQuery пример
$.ajax({
    url: '/ajax/example.html',             // указываем URL и
    dataType : "json",                     // тип загружаемых данных
    success: function (data, textStatus) { // вешаем свой обработчик на функцию success
        $.each(data, function(i, val) {    // обрабатываем полученные данные
            /* ... */
        });
    }
});

Вот как туда попадаёт data, если
function success() {
            // If a local callback was specified, fire it and pass it the data
            if ( s.success ) {
                s.success.call( callbackContext, data, status, xhr );
            }
 
            // Fire the global callback
            if ( s.global ) {
                trigger( "ajaxSuccess", [xhr, s] );
            }
        }

Нету переменных, или я чего не пойму.

micscr 21.05.2010 10:25

Цитата:

Сообщение от mycoding (Сообщение 55913)
http://javascript.ru/blog/mycoding/Pishem-svoj-jquery
Это моя курсовая просто да и интересно тоже.

Ну, курсовая тогда понятно. Кто то минусов тебе туда накидал. Может нужно не Пишем свой jQuery, а Пишем свой js-фреймворк ?

Octane 21.05.2010 10:40

Цитата:

Сообщение от mycoding
if(xhr.status == 200){/*Пришёл ответ*/if(complete){complete();}}

if(xhr.status == 200){/*Пришёл ответ*/if(complete){complete(*!*xhr.responseText*/!*);}}

mycoding 21.05.2010 10:57

Заработало :thanks:


Часовой пояс GMT +3, время: 12:53.