Bugün JavaScript’te asenkron programlama ve API’larla nasıl çalışacağımızı öğreneceğiz. Modern web uygulamalarında veri çekmek ve işlemleri asenkron olarak yönetmek için hayati önem taşır.

1. Senkron ve Asenkron Programlama

1.1. Senkron Programlama

Senkron programlamada kod satırları sırayla ve birinin tamamlanmasını bekleyerek çalışır. Yani bir işlem bitmeden diğeri başlamaz.

console.log("Birinci işlem");

// Zaman alıcı bir işlem
for (let i = 0; i < 1000000000; i++) {}

console.log("İkinci işlem");

Bu kodda, zaman alıcı döngü tamamlanmadan “İkinci işlem” yazdırılmaz — sayfa kilitlenir.

1.2. Asenkron Programlama

Asenkron programlamada işlemler aynı anda veya belirli bir süre sonra başlatılabilir ve diğer kodların çalışmasını engellemez.

console.log("Birinci işlem");

setTimeout(function() {
    console.log("İkinci işlem (2 saniye sonra)");
}, 2000);

console.log("Üçüncü işlem");

“Birinci işlem” ve “Üçüncü işlem” hemen yazdırılır, “İkinci işlem” 2 saniye sonra gelir. Kod akışı bloklanmaz.

2. Callback Fonksiyonları

Callback fonksiyonları, bir işlemin tamamlanmasından sonra çağrılan fonksiyonlardır. Asenkron işlemleri yönetmek için sıkça kullanılır.

function dosyayiOku(dosyaAdi, callback) {
    // Asenkron dosya okuma simülasyonu
    setTimeout(function() {
        let veri = "Dosya içeriği";
        callback(veri);
    }, 1000);
}

dosyayiOku("veri.txt", function(icerik) {
    console.log("Dosya içeriği:", icerik);
});

Callback Hell

Callback fonksiyonlarının iç içe kullanılması kodun okunabilirliğini ve yönetimini zorlaştırabilir — buna “Callback Hell” denir:

setTimeout(function() {
    console.log("1. işlem");
    setTimeout(function() {
        console.log("2. işlem");
        setTimeout(function() {
            console.log("3. işlem");
        }, 1000);
    }, 1000);
}, 1000);

Bunu önlemek için Promise ve async/await yapıları kullanılır.

3. Promiseler

Promise, JavaScript’te asenkron işlemleri yönetmek için kullanılan bir nesnedir. Bir Promise üç durumda olabilir:

Promise Oluşturma

let soz = new Promise(function(resolve, reject) {
    let basarili = true;

    if (basarili) {
        resolve("İşlem başarılı!");
    } else {
        reject("İşlem başarısız!");
    }
});

soz.then(function(sonuc) {
    console.log(sonuc);
}).catch(function(hata) {
    console.error(hata);
});

Promise Zincirleme

Promiseler, birden fazla asenkron işlemi sıralı olarak gerçekleştirmek için zincirlenebilir:

function islem1() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("İşlem 1 tamamlandı");
            resolve();
        }, 1000);
    });
}

function islem2() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("İşlem 2 tamamlandı");
            resolve();
        }, 1000);
    });
}

islem1()
    .then(islem2)
    .then(function() {
        console.log("Tüm işlemler tamamlandı");
    });

4. async ve await

async ve await, asenkron işlemleri yazmayı ve okumayı kolaylaştıran anahtar kelimelerdir.

async Fonksiyonları

Bir fonksiyonu async olarak tanımladığınızda, otomatik olarak bir Promise döndürür.

async function ornekFonksiyon() {
    return "Sonuç";
}

ornekFonksiyon().then(sonuc => {
    console.log(sonuc); // "Sonuç"
});

await Anahtar Kelimesi

await, bir Promise’in çözülmesini bekler ve sonucunu döndürür. Sadece async fonksiyonları içinde kullanılabilir.

function veriGetir() {
    return new Promise(resolve => {
        setTimeout(function() {
            resolve("Veri alındı");
        }, 2000);
    });
}

async function islemYap() {
    console.log("İşlem başlıyor...");
    let sonuc = await veriGetir();
    console.log(sonuc); // "Veri alındı"
    console.log("İşlem bitti");
}

islemYap();

5. fetch API’si ile Veri Çekme

fetch, HTTP istekleri yapmak için kullanılan yerleşik bir JavaScript fonksiyonudur.

Temel Kullanım

fetch("https://jsonplaceholder.typicode.com/posts/1")
    .then(response => response.json())
    .then(data => {
        console.log(data);
    })
    .catch(err => {
        console.error("Hata oluştu:", err);
    });

async/await ile fetch

async function veriAl() {
    try {
        let response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error("Hata oluştu:", error);
    }
}

veriAl();

6. API Nedir ve Nasıl Kullanılır?

API (Application Programming Interface), uygulamaların birbirleriyle iletişim kurmasını sağlayan bir arayüzdür. Web API’ları, HTTP protokolü üzerinden veri alıp göndermemize olanak tanır.

Örnek: Hava Durumu API’si

async function havaDurumuGetir(sehir) {
    let apiKey = "API_KEYİNİZİ_BURAYA_YERLEŞTİRİN";
    let url = `https://api.openweathermap.org/data/2.5/weather?q=${sehir}&appid=${apiKey}&lang=tr&units=metric`;

    try {
        let response = await fetch(url);
        let data = await response.json();

        if (data.cod === 200) {
            console.log(`${sehir} için hava durumu: ${data.main.temp} °C`);
        } else {
            console.error("Şehir bulunamadı.");
        }
    } catch (error) {
        console.error("Hata oluştu:", error);
    }
}

havaDurumuGetir("Ankara");

Not: Gerçek bir API kullanırken API anahtarınızı gizli tutmalısınız. Frontend’de açık API key bulundurmak güvenlik riskidir — backend proxy kullanın.

Günün Özeti

Bugün asenkron JavaScript ve API’larla çalışmayı öğrendik:

Yarın, Gün 5’te modüller ve kütüphane mantığına geçeceğiz — projemizi nasıl organize edeceğimizi ve dış kütüphaneleri nasıl kullanacağımızı öğreneceğiz.