Меню

Техники за напреднали

Влез Излез

AJAX Заявки с кеширане

Миналата седмица написах урок как можем да подобрим user experience-а на нашия сайт, като зареждаме новото съдържание на страниците с JavaScript без презареждане. Тази седмица ще направим промени по кода си, така че да кешираме заредената информация и да не пращаме нови заявки към сървъра, ако не се налага.

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

В този урок ще правим промени директно по кода от предния път.

Нека като за начало да си добавим променлива (обект), в която ще съхраняваме кешираната информация.

jQuery(function ($) {
	var cache = {};
	
	$(document).on('click', 'nav a', function (e) {
		e.preventDefault();
		var link = $(this);
		
		$.get(link.attr('href'), function (data, status, XHR) {
			if (status == 'success') {
				cache[link.attr('href')] = data;
				
				$('section[role="main"]').html($(data).find('section[role="main"]').html());
				
				$('title').html($(data).filter('title').html());
				$('header').html($(data).find('header').html());
			} else {
				// tell the user we could not connect to the server
			}
		});
	});
});

За по-лесен достъп до текущия линк запазвам стойността му в променлива link в click handler-а.

Дефинираме променливата във функцията, която извикваме при DOM Content Loaded. По този начин можем да я достъпваме навсякъде в тази функция, но не и извън нея.

Забележете и начина, по който записваме в този обект информацията, която сме получили при резултат със статус success при нашата get заявка – cache[link.attr('href')] = data;.

Използвайки квадратни скоби можем да достъпим property на обект. Ако в квадратните скоби напишем просто string би било същото, като това да използваме и dot notation syntax (синтаксис с употреба на точки):

object = { prop1: 'value' };
console.log(object.prop1); // извежда "value" в конзолата
object['prop1'] = 'new-value';
console.log(object.prop1); // извежда "new-value"
for (var i = 1; i < 2; i++) {
	object['prop' + i] = 'third-value';
}
console.log(object.prop1); // извежда "third-value"

Предимството при достъпване на белези на абект, използвайки квадратни скоби е, че по този начин можем да създаваме динамично имената на белезите с помощта на променливи. В предния пример виждате как чрез променливата i със стойност 1 динамично генерирам името на property-то "prop1". Подобно нещо не може да се направи с dot notation syntax.

Това предимство използваме и при кеширането. Там задаваме стойност на property, като самото property зависи от адреса на линка. Така можем да генерираме толкова property-та колкото линка имаме, като запазим и самия JavaScript независим от адресите на страниците.

Сега следва да направим така, че при кликване на линк първо да направим проверка дали вече нямаме резултата кеширан и да правим AJAX заявка само по веднъж за един и същ адрес.

jQuery(function ($) {
	var cache = {};
	
	$(document).on('click', 'nav a', function (e) {
		e.preventDefault();
		var link = $(this);
		
		if (typeof(cache[link.attr('href')]) != 'undefined') {
			// show cached content
		} else {
			$.get(link.attr('href'), function (data, status, XHR) {
				if (status == 'success') {
					cache[link.attr('href')] = data;
					
					$('section[role="main"]').html($(data).find('section[role="main"]').html());
					
					$('title').html($(data).filter('title').html());
					$('header').html($(data).find('header').html());
				} else {
					// tell the user we could not connect to the server
				}
			});
		}		
	});
});

Проверката я правим чрез typeof(cache[link.attr('href')) != 'undefined'. Проверка за типа на дадена променлива сме правили и в предишни уроци. Тук отново проверяваме дали типът е различен от "undefined" -- дали променливана (която в случая е във вида на property на обект) съществува.

Ако съществува -- значи вече имаме дадения адрес кеширан и не трябва да правим нова заявка, а само да покажем информацията. Бихме могли просто да копираме функционалността, с която заменяме съдържанието в callback функцията на заявката, но това ще доведе до повтаряне на код.

По добрият начин би бил да извършим това чрез функция, която да викаме в двата случая:

jQuery(function ($) {
	var cache = {};
	
	function showPageContent(data) {
		$('section[role="main"]').html($(data).find('section[role="main"]').html());
		
		$('title').html($(data).filter('title').html());
		$('header').html($(data).find('header').html());
	}
	
	$(document).on('click', 'nav a', function (e) {
		e.preventDefault();
		var link = $(this);
		
		if (typeof(cache[link.attr('href')]) != 'undefined') {
			showPageContent(cache[link.attr('href')]);
		} else {
			$.get(link.attr('href'), function (data, status, XHR) {
				if (status == 'success') {
					cache[link.attr('href')] = data;
					showPageContent(data);
				} else {
					// tell the user we could not connect to the server
				}
			});
		}
	});
});

Можете да видите крайния резултат на https://magadanski.com/demo/ajax-requests-cached/

Забележка: тъй като в случая използваме статични страници, сървърите указват на браузъра, че промяна в скоро време може и да не се забележи, затова самите браузъри кешират нашите заявки. Кодът, който добавихме в този урок, би бил уместен в случай, че страниците ни са генерирани динамично (например с PHP).

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax