jQuery ile AJAX: sayfayı yenilemeden veri göndermek
Form gönderimini sayfa yüklemeden ayırmanın 2014'teki standardı: jQuery $.ajax kullanımı ve pratik örnekler.
Birkaç ay öncesine kadar kullanıcı bir form gönderdiğinde sayfanın yeniden yüklenmesi benim için olağan bir durumdu. Kullanıcı butona basıyor, sayfa flickering yapıyor, aynı sayfa farklı bir mesajla geri geliyor. Çalışıyor ama biraz kaba.
AJAX (Asynchronous JavaScript and XML), tarayıcının sayfayı yeniden yüklemeden sunucuya istek gönderip yanıt almasını sağlayan bir tekniktir. Artık XML yerine çoğunlukla JSON kullanılıyor ama isim kaldı. jQuery’nin $.ajax metodu bu işlemi 2014’te en yaygın kullanılan yol.
Neden jQuery?
JavaScript’in yerleşik XMLHttpRequest nesnesi AJAX için kullanılabilir ama tarayıcılar arası farklılıkları elle ele almak zorunda kalıyorsunuz. jQuery bu karmaşıklığı soyutluyor ve her tarayıcıda aynı şekilde çalışıyor. Bugün hangi projeye baksan jQuery var; bu ortamda başka bir şey öğrenmek için neden yoktu.
Temel $.ajax kullanımı
$.ajax({
url: '/api/yorum-ekle',
method: 'POST',
data: {
yorum: 'Bu içerik çok faydalıydı.',
makale_id: 42
},
success: function(yanit) {
console.log('Başarılı:', yanit);
},
error: function(xhr, durum, hata) {
console.log('Hata:', hata);
}
});
url isteğin gideceği adres, method HTTP yöntemi, data göndereceğiniz veriler. success ve error callback fonksiyonları yanıta göre çalışır.
Form gönderimini AJAX’a bağlamak
Pratikte en sık kullandığım senaryo: kullanıcı formu doldurup gönderiyor, sayfa yenilenmeden işlem tamamlanıyor ve kullanıcıya mesaj gösteriliyor.
HTML tarafı:
<form id="yorumFormu">
<textarea name="yorum" id="yorumAlani"></textarea>
<button type="submit">Gönder</button>
</form>
<div id="mesaj"></div>
JavaScript tarafı:
$('#yorumFormu').on('submit', function(e) {
e.preventDefault(); // Sayfanın yenilenmesini önlüyoruz
var yorum = $('#yorumAlani').val();
$.ajax({
url: '/yorum-ekle',
method: 'POST',
data: { yorum: yorum },
dataType: 'json',
success: function(yanit) {
if (yanit.basarili) {
$('#mesaj').text('Yorumunuz eklendi.').show();
$('#yorumAlani').val('');
}
},
error: function() {
$('#mesaj').text('Bir hata oluştu, tekrar deneyin.').show();
}
});
});
e.preventDefault() satırı çok önemli; olmadan tarayıcı formu normal şekilde gönderir ve sayfa yenilenir.
Sunucu tarafı
PHP tarafında isteği alıp JSON döndürmek yeterli:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$yorum = trim($_POST['yorum'] ?? '');
if (!empty($yorum)) {
// Veritabanına kaydetme işlemi...
echo json_encode(['basarili' => true]);
} else {
echo json_encode(['basarili' => false, 'mesaj' => 'Yorum boş olamaz.']);
}
exit;
}
Content-Type başlığını application/json olarak ayarlamak iyi bir alışkanlık:
header('Content-Type: application/json');
Bu başlığı koymayı unutmak ciddi bir sorun yaratmıyor ama tarayıcı ve istemci kütüphaneleri yanıtı doğru türde işlemek için bu bilgiye güveniyor. Özellikle jQuery’nin dataType: 'json' seçeneği bu başlıkla tutarlı olmalı; tutarsızlık debugging sırasında kafa karıştırabilir.
$.get ve $.post kısayolları
Sık kullanılan HTTP yöntemleri için kısayollar var:
// GET isteği
$.get('/api/makaleler', function(yanit) {
console.log(yanit);
});
// POST isteği
$.post('/api/yorum-ekle', { yorum: 'Merhaba' }, function(yanit) {
console.log(yanit);
});
Bunlar $.ajax’ın kısaltılmış halleri. Basit durumlarda kullanışlı, ama hata yönetimine ihtiyaç duyulduğunda $.ajax daha esnekdir.
Yükleme göstergesi
Kullanıcıya isteğin sürdüğünü bildirmek iyi bir pratik:
$.ajax({
url: '/api/veri',
beforeSend: function() {
$('#yukleniyor').show();
},
complete: function() {
$('#yukleniyor').hide();
},
success: function(yanit) {
// işlem
}
});
beforeSend istek başlamadan, complete ise başarılı ya da başarısız olsun isteğin bitiminde çalışır.
Bir tuzak: complete yerine success içinde göstergeyi kapatmak. Sunucu bir hata döndürdüğünde success çalışmıyor; gösterge ekranda kalıyor. complete her iki durumda da çalıştığından kapatma işlemini buraya koymak doğru.
Güvenlik: CSRF koruması
AJAX isteklerinde sıklıkla atlanan bir konu: CSRF (Cross-Site Request Forgery) koruması. PHP tarafında Laravel ya da başka bir framework kullanıyorsanız, POST istekleri için genellikle bir token doğrulaması bekleniyor.
HTML’deki meta etiketteki token’ı AJAX isteğiyle birlikte göndermek gerekiyor:
<meta name="csrf-token" content="<?php echo csrf_token(); ?>">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajaxSetup ile bir kez tanımlayınca tüm $.ajax çağrıları bu başlığı otomatik ekliyor. Token olmadan gönderilen POST isteği Laravel’de 419 (Page Expired) hatası veriyor; neden hata aldığını anlamak biraz zaman alabiliyor.
Şimdiye kadar öğrendiklerim
AJAX ile sayfa yenileme olmadan çalışan bir arayüz yapmak kullanıcı deneyimini gözle görülür biçimde iyileştirdi. İlk uyguladığımda “işte bu” dedim; sayfanın titrememesi küçük bir detay gibi görünse de fark büyük.
jQuery bu işi kolaylaştırdı ama altında ne döndüğünü anlamak da önemli. XMLHttpRequest’in üstündeki bu soyutlamanın değerini görmek için birini elle yazmayı denemek gerekiyor. Bir kez yazdıktan sonra jQuery’nin neden bu kadar yaygınlaştığı daha iyi anlaşılıyor.
AJAX’ı öğrenirken en çok zorlandığım konu, yanıtı gerçek veri gibi değil bir olay (event) gibi düşünmekti. “Şu veriyi getir, sonra şunu yap” yerine “bu istek tamamlandığında şu fonksiyon çalışsın” şeklinde düşünmek gerekiyor. PHP’den gelen biri için bu zihniyet değişikliği zaman alıyor; çünkü PHP’de her satır bir öncekinin bitmesini bekliyor. JavaScript’te ise beklemek yerine “ne zaman hazır olursa” diyor ve geri çekiliyor. Bu farkı içselleştirince success callback’inin neden o yapıda göründüğü çok daha net oluyor.