Ajax ve XML: Beş adet kötü Ajax kalıbı

0
tongucyumruk
IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

Ajax ve XML: Beş adet kötü Ajax kalıbı

Yaygın Ajax kodu tuzaklarından kaçınma

Düzey: Orta

Jack D Herrington (jherr@pobox.com), Kıdemli Yazılım Mühendisi, Leverage Software Inc.

20 Mart 2007

Bir şeylerin nasıl yanlış yapıldığını anlayarak, bunları doğru bir şekilde yapmaya ilişkin birçok bilgi öğrenebilirsiniz. Kuşkusuz, Zamanuyumsuz JavaScript™ + XML (Ajax) uygulamalarını yazmanın bir doğru, bir de yanlış yolu vardır. Bu makalede, kaçınmak isteyeceğiniz bazı genel kodlama uygulamaları anlatılmaktadır.

İnsanlar her şeyi ilk yaptıklarında doğru yapsalardı, dünya tamamıyla farklı olurdu. Ajax için de bu kural geçerlidir. Bugüne kadar birçok kodlama yaptım, kod yazdım, konuştum ve kendim de dahil Ajax geliştiricilerini destekledim. Bunlar aracılığıyla, Ajax'ta nerelerde doğru ve yanlış yapıldığıyla ilgili çok şey öğrendim. Son makalemde (Beş yaygın Ajax kalıbı: Kullanabileceğiniz yararlı Ajax tasarım kalıpları), Ajax uygulamalarını doğru bir şekilde yazmaya ilişkin beş kalıp sundum. Bu makalede de Ajax kodunda sık sık gördüğüm beş kötü kalıbı anlatacağım.

Kötü kalıp (anti-pattern) nedir diye sorabilirsiniz? Kötü kalıp, herkesin kaçınması gereken bir sorun olarak yeterince sık görülen bir uygulama tasarımı kusurudur. Burada genel olarak konuşuyorum. Sözdizimi hataları ve bağlayıcı sorunları buna dahil edilmemelidir.

Çoğu geliştirici iyi bir kötü kalıp örneğini duymuştur: Web sitelerinde SQL (Structured Query Language; Yapısal Sorgu Dili) güvenlik açığı saldırılarına neden olan SQL kitaplıklarının yanlış kullanımı. Bu kötü kalıp, şirketlerin gelirlerini kaybetmelerine, müşteri kayıtlarının açığa çıkmasına neden olmuştur ve ne yazık ki, her programlama dilinde gerçekleştirilebilmektedir. Bu nedenle, bunun nasıl ve neden olduğunu ve bundan nasıl kaçınılacağını anlamak önemlidir.

Bu, kötü Ajax kalıpları için de geçerlidir. Bu kusurların şirketlerin gelirlerinde milyarlarca dolarlık kayba neden olacağını söylemiyorum. Ancak, bunlar sunucuların arızalanmasına neden olabilir ya da müşteri deneyimini kötüleştirebilirler ve hem sinir bozucu, hem de pahalıya mal olabilirler.

Nelerin yanlış gidebileceğini anlarsanız, çok şey öğrenebilirsiniz. Genellikle, Ajax'ın yalnızca bir sayfa yüklendikten sonra sunucudan XML verilerini almak için kullanılan bir yöntem olduğu düşünülür. Bu çok sınırlı bir görüştür ve yanlış uygulandığında, uygulamalarda performans sorunlarına neden olabilir. Bu makalede, bunun neden yanlış olduğunu ve bunu nasıl düzeltebileceğinizi göstereceğim.

İhtiyacınız olmadığında bir zamanlayıcıyı yoklama

Gördüğüm Ajax sorunlarının birçoğu, JavaScript dilinde oluşturulan zamanlayıcı işlevselliğinin yanlış kullanılmasından kaynaklanıyor. Anahtar yöntem, window.setInterval() yöntemidir. Bu yöntemi ne zaman görürseniz görün, aklınızda hemen bir soru işareti oluşmalıdır: Neden bu kişi bir zamanlayıcı kullanıyor? Elbette, zamanlayıcıların kendi kullanım amaçları vardır -- canlandırmalar gibi.

window.setInterval() yöntemi, sayfanın belirli aralıklarla -- örneğin, her saniye gibi -- belirli bir işlevi geri arayacağını belirtir. Konu bu zamanlayıcılar olduğunda çoğu tarayıcı iyi olduğunu iddia eder, ancak temel olarak JavaScript tek iş parçacıklı çalıştığından bunu nadiren başarırlar. Bir saniye değerini ayarlarsanız, geri aramayı 1 saniye, 1.2 saniye ya da 9 saniye sonra alabilirsiniz.

Zamanlayıcının kesinlikle gerekli olmadığı bir örnek, Ajax isteğinin bitişini izlemektir. Liste 1'deki örneğe bakın.


Liste 1. Antipat1a_polling.html
        
<html><script>
var req = null;

function loadUrl( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.open('GET', url, true);
    req.send('');
  }
}

window.setInterval( function watchReq() {
    if ( req != null && req.readyState == 4 && req.status == 200 ) {
      var dobj = document.getElementById( 'htmlDiv' );
      dobj.innerHTML = req.responseText;
      req = null;
   }
 }, 1000 );

var url = window.location.toString();
url = url.replace( /antipat1a_polling.html/, 'antipat1_content.html' );
loadUrl( url );
</script><body>
Dynamic content is shown between here:<br/>

<div id="htmlDiv" style="border:1px solid black;padding:10px;">
</div>And here.</body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat1a_polling.html bağlantısını görüntülemek üzere yeni pencerede
açantipat1a_polling.html sayfasının çevrimiçi sürümünü görüntüleyin.

setInterval çağrısını alıncaya kadar her şey yolundaymış gibi görünür. Bu çağrı, isteğin durumunu izleyecek ve daha sonra, yüklenen malzemeden sayfanın içeriğini belirleyecek bir zamanlayıcı ayarlar.

Bir isteğin tamamlandığının kısa sürede nasıl anlaşılacağına ilişkin soruna daha iyi bir çözüm göstereceğim. Bu arada, Liste 2'de sayfanın istekte bulunduğu dosya gösterilmektedir.


Liste 2. Antipat1_content.html
 
<b>Hello there</b>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat1_content.html bağlantısını görüntülemek üzere yeni pencerede
açantipat1_content.html sayfasının çevrimiçi sürümünü görüntüleyin.

Şekil 1'de, sayfa, tarayıcımda görüntülendiği şekilde gösterilmektedir.


Şekil 1. HTML belgesine yerleştirilen içerik
HTML belgesine yerleştirilen
içerik

Şimdi kendinize şunu sorabilirsiniz: "Peki, bu çalışıyor, değil mi? Bozuk değilse neden düzeltiyoruz?" Aslında bozuk, çünkü çok yavaş çalışıyor. Zamanlayıcı bir saniyelik aralığa ayarlandığında, zamanlayıcı kapanana kadar istek çoktan tamamlanır. Bu nedenle, sayfa önce boş bir kutuyla görüntülenir, daha sonra bir saniye beklersiniz ve sonra içerik görüntülenir. Çok kötü!

Çözüm nedir? Ajax, doğası gereği zamanuyumsuzdur. Bir isteğin ne zaman tamamlandığını görmek için bir yoklama döngüsüne ihtiyacınız yok mu?

Görünüşe göre, pek de değil. Liste 3'te gösterdiğim gibi, XMLHTTPRequest nesnesinin tamamı, onreadystatechange adı verilen bir geri arama düzeneği sağlar. (Ne güzel bir ad, VAX PDP/11s'yi hatırlatıyor).


Liste 3. Antipat1a_fixed.html
  
<html><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'htmlDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) {
  ...
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /antipat1a_fixed.html/, 'antipat1_content.html' );
loadUrl( url );
</script>
...

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat1a_fixed.html bağlantısını görüntülemek üzere yeni pencerede
açantipat1a_fixed.html sayfasının çevrimiçi sürümünü görüntüleyin.

Bu yeni kod, yalnızca istek nesnesinin, bu onreadystatechange geri aramasına yanıt olarak değişip değişmediğine bakar. Daha sonra, tamamlandığında sayfayı günceller.

Sonuç, yıldırım hızıyla yüklenen bir sayfadır. Sayfa görüntülenir ve neredeyse yüklenir yüklenmez yeni içerik kutuya yerleştirilir. Neden? Çünkü, istek tamamlanır tamamlanmaz, kod çağrılır ve sayfa doldurulur. Anlamsız zamanlayıcılarla ortalığı karıştırmaya gerek yoktur.

Başka bir yoklama kötü kalıp değişkeninde, bir sayfa bir isteği sunucuya, istek değişmemiş olsa bile üst üste yeniden sunar. Liste 4'te gösterilen arama sayfasını ele alalım.


Liste 4. Antipat1b_polling.html
        
<html><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'htmlDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) {
  ...
}

window.setInterval( function watchSearch() {
  var url = window.location.toString();
  var searchUrl = 'antipat1_content.html?s='+searchText.value;
  url = url.replace( /antipat1b_polling.html/, searchUrl );
  loadUrl( url );
 }, 1000 );

</script><body><form>
Search <input id="searchText" type="text">:<br/>

<div id="htmlDiv" style="border:1px solid black;padding:10px;">
</div></form></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat1b_polling.html bağlantısını görüntülemek üzere yeni pencerede
açantipat1b_polling.html sayfasının çevrimiçi sürümünü görüntüleyin.

Sayfayı Şekil 2'de tarayıcımda çalıştığı şekliyle görebilirsiniz.


Şekil 2. Dinamik yanıt alanlı arama alanı
Dinamik yanıt alanlı arama
alanı

Çok hoş. Görünüşünden, bu sayfa birçok şeyi anlatmaktadır. Arama metnini değiştirdiğimde, sonuç alanı yeni ölçüte dayalı olarak değişiyor (aslında değişmiyor, ancak isteğin arkasında gerçek bir arama motoru olsa, değişirdi.)

Buradaki sorun, JavaScript kodunun, arama alanındaki içerik değişmese bile isteği tekrarlamak için window.setInterval öğesini kullanmasıdır. Bu, ağ bant genişliğinin ve sunucu süresinin harcanmasına neden olur. Sık kullanılan sitelerde bu ikisi korkunç bir birleşim olabilir.

Çözüm, Liste 5'te gösterilen şekilde arama kutusunda olay geri aramalarını kullanmaktır.


Liste 5. Antipat1b_fixed.html
  
<html><script>
var req = null;
function processReqChange() { ... }
function loadUrl( url ) { ...  }

var seachTimer = null;
function runSearch()
{
  if ( seachTimer != null )
    window.clearTimeout( seachTimer );
  seachTimer = window.setTimeout( function watchSearch() {
    var url = window.location.toString();
    var searchUrl = 'antipat1_content.html?s='+searchText.value;
    url = url.replace( /antipat1b_fixed.html/, searchUrl );
    loadUrl( url );
    seachTimer = null;
   }, 1000 );
}
</script><body><form>
Search <input id="searchText" type="text" onkeyup="runSearch()">:<br/>

<div id="htmlDiv" style="border:1px solid black;padding:10px;">
</div></form></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat1b_fixed.html bağlantısını görüntülemek üzere yeni pencerede
açantipat1b_fixed.html sayfasının çevrimiçi sürümünü görüntüleyin.

Burada, runSearch() işlevini, arama kutusunun onkeyup() yöntemine bağladım. Bu şekilde, kullanıcı arama kutusuna bir şey yazdığında geri aranmamı sağladım.

runSearch() işlevinin yaptığı oldukça güzeldir. Sunucuya çağrıda bulunacak ve aramayı çalıştıracak ikinci bir yöntem için tek bir zamanaşımı değeri ayarlar. Ayrıca, ayarlamadan önce geçmişse bu zamanaşımı değerini temizler. Neden? Çünkü bu, kullanıcının çok miktarda metin yazmasına olanak tanır; daha sonra, kullanıcı son tuşa bastıktan bir saniye sonra arama çalıştırılır. Bu şekilde, kullanıcı sürekli olarak titreyen görüntüyle rahatsız olmaz.


Geri aramada dönüş sonuçlarının incelenmemesi

Birçok kötü Ajax kalıbı, XMLHTTPRequest nesnesinin mekanizması yanlış anlaşıldığı için ortaya çıkar. Sık karşılaştıklarımdan biri, kullanıcıların geri aramadaki nesnenin readyState ya da status alanlarını incelememelerinden kaynaklanır. Ne demek istediğimi daha iyi anlamak için Liste 6'ya bakın.


Liste 6. Antipat2_nocheck.html
 
<html><script>
var req = null;
function processReqChange() {
  var dobj = document.getElementById( 'htmlDiv' );
  dobj.innerHTML = req.responseText;
}
...

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat2_nocheck.html bağlantısını görüntülemek üzere yeni pencerede
açantipat2_nocheck.html sayfasının çevrimiçi sürümünü görüntüleyin.

Her şey düzgün görünüyor. Küçük isteklerde ve bazı tarayıcılarda, düzgün çalışabilir. Ancak, birçok istek, tamamlanmadan önce onreadystatechange işleyicisine birkaç çağrı gönderecek kadar büyüktür. Bu nedenle, geri aramanız eksik verilerle çalışıyor olabilir.

Bunun doğru şekli Liste 7'de gösterilmiştir.


Liste 7. Antipat2_fixed.html

<html><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'htmlDiv' );
    dobj.innerHTML = req.responseText;
  }
}
...

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat2_fixed.html bağlantısını görüntülemek üzere yeni pencerede
açantipat2_fixed.html sayfasının çevrimiçi sürümünü görüntüleyin.

Ek koda gerek yoktur ve her tarayıcıda çalışır.

Bu sorunun Windows® Internet Explorer® 7 programında, diğer tarayıcılardan daha ciddi olduğunu fark ettim. Internet Explorer 7, onreadystatechange nesnesini çok fazla geri arıyor -- küçük isteklerde bile çok. Bu nedenle, en azından işleyicileriniz doğru yazılmış olmalı.


HTML'in daha uygun olacağı durumlarda karmaşık XML geçirilmesi

Birlikte çalıştığım bir şirkette, tüm konuşmalar "ağın ön saflarında bilgi" olması üzerineydi. Aslında fikir basitti; işin tümünü sunucuda yapmak yerine masaüstünde yapmak için tarayıcının akıllı özellikleri kullanmak.

Ancak, sayfalarınıza ne kadar çok bilgi koyarsanız orada o kadar çok JavaScript kodu kullanmanız gerekir. Bunun büyük bir olumsuz tarafı vardır: Tarayıcı uyumluluğu. Önemsiz olmayan her JavaScript kodu satırını gerçekten de tüm popüler tarayıcılarda -- ya da en azından, genellikle müşterilerinizin kullandıklarında -- sınamanız gerekir. Ve bu, iş anlamına gelir. Örneğin, Liste 8'deki karmaşık Ajax koduna bakalım.


Liste 8. Antipat3_complex.html
 
<html><head><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 && req.responseXML ) {
    var dtable = document.getElementById( 'dataBody' );
    var nl = req.responseXML.getElementsByTagName( 'movie' );
    for( var i = 0; i < nl.length; i++ ) {
      var nli = nl.item( i );
      var elYear = nli.getElementsByTagName( 'year' );
      var year = elYear.item(0).firstChild.nodeValue;
      var elTitle = nli.getElementsByTagName( 'title' );
      var title = elTitle.item(0).firstChild.nodeValue;

      var elTr = dtable.insertRow( -1 );

      var elYearTd = elTr.insertCell( -1 );
      elYearTd.innerHTML = year;

      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = title;
} } }

function loadXMLDoc( url ) {
  if(window.XMLHttpRequest) {
    try { req = new XMLHttpRequest();
    } catch(e) { req = false; }
  } else if(window.ActiveXObject) {
    try { req = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
    try { req = new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { req = false; }
  } }
  if(req) {
    req.onreadystatechange = processReqChange;
    req.open('GET', url, true);
    req.send('');
  }
}

var url = window.location.toString();
url = url.replace( /antipat3_complex.html/, 'antipat3_data.xml' );
loadXMLDoc( url );

</script></head><body>
<table cellspacing="0" cellpadding="3" width="100%"><tbody id="dataBody">
<tr>
  <th width="20%">Year</th>
  <th width="80%">Title</th>

</tr>
</tbody></table></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat3_complex.html bağlantısını görüntülemek üzere yeni pencerede
açantipat3_complex.html sayfasının çevrimiçi sürümünü görüntüleyin.

Bu kod, Liste 9'da gösterilen XML dosyasındaki verileri okur ve bunları, bir tablo halinde düzenler.


Liste 9. Antipat3_data.xml
      
<movies>
  <movie>
    <year>1993</year>
    <title>Jurassic Park</title>

  </movie>
  <movie>
    <year>1997</year>
    <title>The Lost World: Jurassic Park</title>
  </movie>

  <movie>
    <year>2001</year>
    <title>Jurassic Park III</title>
  </movie>
</movies>


Sonucu Şekil 3 içinde görebilirsiniz.


Şekil 3. Karmaşık film listesi sayfası
Karmaşık film listesi sayfası

Bu, kötü bir kod değildir. Aslında yalnızca nispeten basit bir görevi gerçekleştirmek için çok fazla kod kullanılmıştır. Sonuçta görüntülenen sayfa o kadar da karmaşık değildir. İstemci tarafında sıralama ya da arama yapılamaz. Aslında, XML ile HTML arasındaki bu karmaşık dönüştürmeyi gerçekleştirmek için neredeyse hiç neden yoktur.

Sunucunun, Liste 10'daki gibi XML yerine HTML kullanması daha kolay olmaz mıydı?


Liste 10. Antipat3_fixed.html
 
<html><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dobj = document.getElementById( 'tableDiv' );
    dobj.innerHTML = req.responseText;
  }
}

function loadUrl( url ) { ... }

var url = window.location.toString();
url = url.replace( /antipat3_fixed.html/, 'antipat3_content.html' );
loadUrl( url );

</script><body><div id="tableDiv"></div></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat3_fixed.html bağlantısını görüntülemek üzere yeni pencerede
açantipat3_fixed.html sayfasının çevrimiçi sürümünü görüntüleyin.

Gerçekten de daha basit. Tüm karmaşık tablo satırı ve hücre yaratma kodu, sayfadaki bir <div> biçim iminin tek bir innerHTML takımıyla değiştirildi. İşte bu!

Sunucudan döndürülen HTML Liste 11'de gösterilmiştir.


Liste 11. Antipat3_content.html
       
<table cellspacing="0" cellpadding="3" width="100%">
<tbody id="dataBody">
<tr>
  <th width="20%">Year</th>

  <th width="80%">Title</th>
</tr>
<tr>
  <td>1993</td>
  <td>Jurassic Park</td>

</tr>
<tr>
  <td>1997</td>
  <td>The Lost World: Jurassic Park</td>
</tr>
<tr>

  <td>2001</td>
  <td>Jurassic Park III</td>
</tr>
</tbody>
</table>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat3_content.html bağlantısını görüntülemek üzere yeni pencerede
açantipat3_content.html sayfasının çevrimiçi sürümünü görüntüleyin.

Her şeyde olduğu gibi, işlemenin sunucu ya da istemci tarafında gerçekleşmesi işin gereksinimlerine bağlıdır. Bu örnekte, iş nispeten basittir: Bir film tablosu oluşturma. İş daha karmaşık olsaydı -- sıralama, arama, ekleme ya da silme ya da bir film tıklatıldığında daha fazla bilginin gösterilmesi gibi dinamik etkileşim -- istemci tarafında daha karmaşık kod görülebilirdi. Aslında, bu makalenin sonunda, sunucuya çok fazla yük yerleştirmeye ilişkin karşı sav hakkında bilgi verirken istemci tarafında sıralama yapmayı göstereceğim.

Tüm bunların belki de en mükemmel örneği Google Maps uygulamasıdır. Google Maps, zengin istemci tarafı kodu ile sunucu tarafındaki akıllı harita altyapısını karışık kullanarak mükemmel bir iş yapar. Bu hizmeti, nerede hangi işlemenin gerçekleştirileceğinin nasıl belirleneceğine örnek olarak gösteriyorum.


JavaScript kodu geçirilmesi gerekirken XML kodunun geçirilmesi

Web tarayıcılarının XML veri kaynaklarını okumasını sağlamak ve bunları dinamik olarak dönüştürmekle ilgili yapılan tüm bu reklam karşısında, kullanılabilecek tek yöntemin bu olduğunu düşünebilirsiniz. Ancak, yanılırsınız. Çok zeki mühendisler, XML yerine JavaScript kodunu göndermek için Ajax aktarım teknolojisini kullanmışlardır. Liste 12'deki film tablosu örneğini ele alalım.


Liste 12. Antipat4_fixed.html
 
<html><head><script>
var req = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    var dtable = document.getElementById( 'dataBody' );
    var movies = eval( req.responseText );
    for( var i = 0; i < movies.length; i++ ) {
      var elTr = dtable.insertRow( -1 );
      var elYearTd = elTr.insertCell( -1 );
      elYearTd.innerHTML = movies[i].year;
      var elTitleTd = elTr.insertCell( -1 );
      elTitleTd.innerHTML = movies[i].name;
} } }

function loadXMLDoc( url ) { ... }

var url = window.location.toString();
url = url.replace( /antipat4_fixed.html/, 'antipat4_data.js' );
loadXMLDoc( url );

</script></head><body>
<table cellspacing="0" cellpadding="3" width="100%">
<tbody id="dataBody"><tr>
  <th width="20%">Year</th>
  <th width="80%">Title</th>

</tr></tbody></table></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat4_fixed.html bağlantısını görüntülemek üzere yeni pencerede
açantipat4_fixed.html sayfasının çevrimiçi sürümünü görüntüleyin.

Bu, sunucudan XML okumak yerine JavaScript kodunu okur. Daha sonra, kod, tabloyu hızlı bir şekilde oluşturmak için kullanabileceği verileri almak üzere JavaScript kodundaki eval() işlevini kullanır.

JavaScript verileri Liste 13'te gösterilmiştir.


Liste 13. Antipat4_data.js
    
[ { year: 1993, name: 'Jurassic Park' },
  { year: 1997, name: 'The Lost World: Jurassic Park' },
  { year: 2001, name: 'Jurassic Park III' } ]

Bu işlevi kullanmak için sunucuyu JavaScript dilinde konuşturmanız gerekir. Ancak, bu o kadar da zor bir şey değildir. Popüler Web dillerinin çoğu zaten JavaScript Object Notation (JSON) çıktısını desteklemektedir.

Bunun yararları açıktır. Bu örnekte, JavaScript dili kullanılarak istemciye yüklenen veri büyüklüğünde %52 tasarruf sağlanmıştır. Ayrıca, performans artışı da gerçekleştirilmiştir. JavaScript sürümünün okunması %9 daha hızlı olmuştur. %9 çok büyük bir değer gibi görünmeyebilir, ancak bunun çok basit bir örnek olduğu unutulmamalıdır. Daha büyük veri blokları ya da daha karmaşık yapılar, daha fazla XML ayrıştırma kodu gerektirirken, JavaScript kodu değişmeden kalır.


Sunucu tarafında çok fazla iş yapılması

Sunucu tarafında az iş yapılmasının karşı savı sunucuda çok iş yapılmasıdır. Daha önce belirttiğim gibi bu dengeleyici bir işlemdir. Ancak, sunucudaki iş yükünü azaltmaya bir örnek olarak, film tablosunun istemci tarafında nasıl sıralanacağını göstermek istiyorum.

Liste 14'te sıralanabilir bir film tablosu gösterilmiştir.


Liste 14. Antipat5_sort.html
  
<html><head><script>

var req = null;
var movies = null;
function processReqChange() {
  if (req.readyState == 4 && req.status == 200 ) {
    movies = eval( req.responseText );
    runSort( 'year' );
} }

function runSort( key )
{
  if ( key == 'name' )
    movies.sort( function( a, b ) {
      if ( a.name < b.name ) return -1;
      if ( a.name > b.name ) return 1;
      return 0;
    } );
  else
    movies.sort( function( a, b ) {
      if ( a.year < b.year ) return -1;
      if ( a.year > b.year ) return 1;
      return 0;
    } );
  var dtable = document.getElementById( 'dataBody' );
  while( dtable.rows.length > 1 ) dtable.deleteRow( 1 );
  for( var i = 0; i < movies.length; i++ ) {
    var elTr = dtable.insertRow( -1 );
    var elYearTd = elTr.insertCell( -1 );
    elYearTd.innerHTML = movies[i].year;
    var elTitleTd = elTr.insertCell( -1 );
    elTitleTd.innerHTML = movies[i].name;
  }
}

function loadXMLDoc( url ) { ... }

var url = window.location.toString();
url = url.replace( /antipat5_sort.html/, 'antipat4_data.js' );
loadXMLDoc( url );
</script></head><body>

<table cellspacing="0" cellpadding="3" width="100%">
<tbody id="dataBody"><tr>
  <th width="20%"><a href="javascript: void runSort('year')">Year</a></th>
  <th width="80%"><a href="javascript: void runSort('name')">Title</a></th>

</tr></tbody></table></body></html>

Canlı bir ortamda bunun nasıl görüneceğini görmek için antipat5_sort.html bağlantısını görüntülemek üzere yeni pencerede
açantipat5_sort.html sayfasının çevrimiçi sürümünü görüntüleyin.

Bu, oldukça basit bir örnektir. Özellikle, birden çok sayfada gösterilebilecek uzun film listelerinde işe yaramaz. Ancak, hızlı bir şekilde, sayfayı yenilemeye gerek kalmadan sıralanan bir tablo ile, sunucuyu fazla zorlamayan, sıradan bir sıralama işini kolay bir şekilde bir araya getirme konusunda iyi bir örnektir.


Sonuç

Ajax konusunda birçok makale yazdım ve Ajax'la ilgili birçok çalışma yaptım. IBM developerWorks üzerindeki Ajax forumu katılımcılarındanım. Dolayısıyla, Ajax ve Ajax'ın nasıl doğru ve yanlış kullanıldığı konularında birkaç şey biliyorum. Sık karşılaştığım durumlardan birisi, geliştiricilerin, Ajax'ın yalnızca bazı XML, JavaScript ya da HTML kodlarını tarayıcıya gönderdiğini düşünerek Ajax'ın karmaşıklığını hafife almasıdır. Ben, Ajax platformunu tam bir tarayıcı olarak görüyorum -- aslında, popüler tarayıcılardan oluşan tam bir takım, çünkü tüm tarayıcıların garipliklerini bilmeniz gerekir.

Sonuçta konu şuraya geliyor: Ajax'la ilgili öğrenilmesi gereken çok şey ve yol boyunca yapılabilecek çok sayıda hata var. Umarım, bu makale bazı tuzaklardan kaçınmanıza ya da içine düştüğünüzde kurtulmanıza yardımcı olur. Her iki durumda da, başarılarınızdan çok şey öğrenebileceğiniz gibi genellikle hatalarınızdan daha çok şey öğrenebilirsiniz.



Kaynaklar

Bilgi Edinme
  • developerWorks XML zone sitesi : developerWorks XML zone sitesinden XML ile ilgili her şeyi öğrenebilirsiniz.

  • JSON ana sayfası: Sunucudan istemciye JavaScript Object Notation verilerinin geçirilmesi için bir başvuru noktası olan JSON sayfasını ziyaret edebilirsiniz.

  • ECMA International sitesi: Burada, gerçekte ECMAScript olarak bilinen JavaScript tanımlarını bulabilirsiniz.

  • AjaxPatterns: Tamamen bu konuya ayrılmış olan bu siteyi keşfedebilirsiniz.

  • Design Patterns (Erich Gamma ve diğerleri, Addison-Wesley, 1995): Yazılım mühendisliğinde kalıpların kullanılmasına ilişkin yeni ufuklar açan bu kitabı okuyabilirsiniz.

  • Ajax Design Patterns (Michael Mahemoff, O’Reilly, 2006): Özellikle Ajax ile ilgili tasarım kalıplarını kapsayan yeni bir kaynak olan bu kitabı okuyabilirsiniz.

  • IBM XML sertifikası : XML ve ilgili teknolojilerde nasıl bir IBM Sertifikalı Geliştirici olabileceğinizi öğrenebilirsiniz.

  • XML teknik kitaplığı: Çok çeşitli teknik makaleler ve ipuçları, senaryolar, standartlar ve IBM Redbook yayınları için developerWorks XML Zone sitesine bakabilirsiniz.

  • developerWorks teknik içerikli etkinlikler ve Web yayınları: Bu oturumlardaki teknolojiyi takip edebilirsiniz.

  • Ajaxian : Bu harika kaynakla, Ajax ve bunu kullanan ön uç pencere bileşenlerle ilgili gelişmeleri izleyebilirsiniz.


Tartışma


Yazar hakkında

Jack D. Herrington, 20 yıldan fazla deneyime sahip, kıdemli bir yazılım mühendisidir. Yazmış olduğu üç kitap vardır: Code Generation in Action, Podcasting Hacks ve PHP Hacks. Ayrıca, 30'dan fazla makale de yazmıştır. Jack Herrington'a jherr@pobox.com adresinden erişebilirsiniz.

İlgili Yazılar

UNIX Dilinde Konuşma, Bölüm 3: Her şeyi komut satırından yapın

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

Geniş bir Linux kümesinin kurulması, Bölüm 2

tongucyumruk

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

developerWorks: Yüksek performanslı Linux kümeleme 2: Çalışan Bir Küme Oluşturma

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

Yeni kullanıcılar için UNIX ipuçları, Bölüm 2:vi metin düzenleyicisi

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.

UNIX Dilinde Konuşma, Bölüm 4: UNIX sahiplik kuralları ve izinleri

butch

IBM Türkiye ve Fazlamesai.net işbirliği ile dilimize kazandırılan yeni bir IBM developerWorks makalesi ile karşınızdayız. Diğer makalelere buradan ulaşabilirsiniz.

Makalenin özgün haline bu adresten ulaşabilirsiniz.