C
Bölüm 7: Asenkron JavaScript ve Modern Özellikler
Genel Bakış

Bölüm 7: Asenkron JavaScript ve Modern Özellikler

15 Haziran 2025
12 dk okuma süresi
asenkron-javascript-modern-ozellikler

Asenkron Programlama Nedir?

Asenkron programlama, kodun sıralı çalışmasını beklemeden diğer işlemlerin devam edebilmesini sağlar. Web geliştirmede özellikle API çağrıları, dosya okuma/yazma ve zamanlayıcılar için kritiktir.

Senkron vs Asenkron

// Senkron kod - her satır sırayla çalışır
console.log('1. İlk işlem');
console.log('2. İkinci işlem');
console.log('3. Üçüncü işlem');
// Çıktı: 1, 2, 3 (sırayla)
 
// Asenkron kod - bazı işlemler bekletilir
console.log('1. İlk işlem');
setTimeout(() => {
    console.log('2. Gecikmeli işlem');
}, 1000);
console.log('3. Üçüncü işlem');
// Çıktı: 1, 3, 2 (1 saniye sonra)

Callback Fonksiyonlar

Temel Callback Kullanımı

// Basit callback örneği
function islemTamamlaninca(sonuc) {
    console.log('İşlem tamamlandı:', sonuc);
}
 
function uzunIslem(callback) {
    console.log('İşlem başladı...');
    setTimeout(() => {
        let sonuc = 'Başarılı!';
        callback(sonuc);
    }, 2000);
}
 
uzunIslem(islemTamamlaninca);
 
// Anonim callback
uzunIslem(function(sonuc) {
    console.log('Anonim callback:', sonuc);
});
 
// Arrow function callback
uzunIslem(sonuc => console.log('Arrow callback:', sonuc));

Callback Hell (Callback Cehennemi)

// İç içe callback'ler - kaçınılması gereken durum
function kullaniciBilgisiAl(id, callback) {
    setTimeout(() => {
        callback({id, isim: 'Furkan', departmanId: 5});
    }, 1000);
}
 
function departmanBilgisiAl(departmanId, callback) {
    setTimeout(() => {
        callback({id: departmanId, isim: 'IT Departmanı'});
    }, 1000);
}
 
function projeListesiAl(departmanId, callback) {
    setTimeout(() => {
        callback(['Proje A', 'Proje B', 'Proje C']);
    }, 1000);
}
 
// Callback hell - okunması zor!
kullaniciBilgisiAl(123, function(kullanici) {
    departmanBilgisiAl(kullanici.departmanId, function(departman) {
        projeListesiAl(departman.id, function(projeler) {
            console.log(`${kullanici.isim} (${departman.isim}) - Projeler:`, projeler);
        });
    });
});

Promise (Söz) Kavramı

Promise Temelleri

// Promise oluşturma
let basitPromise = new Promise((resolve, reject) => {
    let basarili = Math.random() > 0.5;
    
    setTimeout(() => {
        if (basarili) {
            resolve('İşlem başarılı!');
        } else {
            reject('İşlem başarısız!');
        }
    }, 1000);
});
 
// Promise kullanma
basitPromise
    .then(sonuc => {
        console.log('Başarı:', sonuc);
    })
    .catch(hata => {
        console.log('Hata:', hata);
    })
    .finally(() => {
        console.log('İşlem tamamlandı (her durumda çalışır)');
    });

Promise States (Durumları)

// Pending (Bekliyor)
let bekleyenPromise = new Promise((resolve, reject) => {
    // Henüz tamamlanmadı
});
 
// Fulfilled (Başarılı)
let basariliPromise = Promise.resolve('Başarılı sonuç');
 
// Rejected (Başarısız)
let basarisizPromise = Promise.reject('Hata mesajı');
 
// Durum kontrolü
console.log(basariliPromise); // Promise {<fulfilled>: "Başarılı sonuç"}

Promise Chain (Zincir)

function kullaniciBilgisiAl(id) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({id, isim: 'Furkan', departmanId: 5});
        }, 1000);
    });
}
 
function departmanBilgisiAl(departmanId) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({id: departmanId, isim: 'IT Departmanı'});
        }, 1000);
    });
}
 
function projeListesiAl(departmanId) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(['Proje A', 'Proje B', 'Proje C']);
        }, 1000);
    });
}
 
// Promise chain - çok daha temiz!
kullaniciBilgisiAl(123)
    .then(kullanici => {
        console.log('Kullanıcı:', kullanici);
        return departmanBilgisiAl(kullanici.departmanId);
    })
    .then(departman => {
        console.log('Departman:', departman);
        return projeListesiAl(departman.id);
    })
    .then(projeler => {
        console.log('Projeler:', projeler);
    })
    .catch(hata => {
        console.error('Hata oluştu:', hata);
    });

Promise.all ve Promise.race

// Paralel işlemler - hepsi tamamlanana kadar bekle
let promise1 = fetch('/api/kullanicilar');
let promise2 = fetch('/api/departmanlar');
let promise3 = fetch('/api/projeler');
 
Promise.all([promise1, promise2, promise3])
    .then(responses => {
        console.log('Tüm API çağrıları tamamlandı:', responses);
        // Hepsi başarılı olursa çalışır
    })
    .catch(hata => {
        console.log('En az bir API çağrısı başarısız:', hata);
        // Herhangi biri başarısız olursa çalışır
    });
 
// İlk tamamlanan için bekle
Promise.race([promise1, promise2, promise3])
    .then(response => {
        console.log('İlk tamamlanan:', response);
    });
 
// Promise.allSettled - hepsinin sonucunu bekle (başarısız olanlar dahil)
Promise.allSettled([promise1, promise2, promise3])
    .then(sonuclar => {
        sonuclar.forEach((sonuc, indeks) => {
            if (sonuc.status === 'fulfilled') {
                console.log(`Promise ${indeks} başarılı:`, sonuc.value);
            } else {
                console.log(`Promise ${indeks} başarısız:`, sonuc.reason);
            }
        });
    });

async/await (Modern Asenkron Kod)

Temel async/await Kullanımı

// async function tanımlama
async function veriAl() {
    try {
        let kullanici = await kullaniciBilgisiAl(123);
        let departman = await departmanBilgisiAl(kullanici.departmanId);
        let projeler = await projeListesiAl(departman.id);
        
        console.log('Kullanıcı:', kullanici);
        console.log('Departman:', departman);
        console.log('Projeler:', projeler);
        
        return {kullanici, departman, projeler};
    } catch (hata) {
        console.error('Veri alırken hata:', hata);
        throw hata;
    }
}
 
// async function çağırma
veriAl()
    .then(sonuc => console.log('Tüm veriler:', sonuc))
    .catch(hata => console.error('Ana hata:', hata));

Paralel await İşlemleri

async function parallelVeriAl() {
    try {
        // Sıralı - yavaş (3 saniye)
        let kullanici = await kullaniciBilgisiAl(123);
        let ayarlar = await ayarlarAl(123);
        let bildirimler = await bildirimlerAl(123);
        
        // Paralel - hızlı (1 saniye)
        let [kullanici2, ayarlar2, bildirimler2] = await Promise.all([
            kullaniciBilgisiAl(123),
            ayarlarAl(123),
            bildirimlerAl(123)
        ]);
        
        return {kullanici: kullanici2, ayarlar: ayarlar2, bildirimler: bildirimler2};
    } catch (hata) {
        console.error('Paralel veri alma hatası:', hata);
    }
}

Error Handling with async/await

async function guvenliVeriAl(id) {
    try {
        let kullanici = await kullaniciBilgisiAl(id);
        
        if (!kullanici) {
            throw new Error('Kullanıcı bulunamadı');
        }
        
        let departman = await departmanBilgisiAl(kullanici.departmanId);
        
        return {kullanici, departman};
    } catch (hata) {
        if (hata.message === 'Kullanıcı bulunamadı') {
            console.log('Özel hata işleme:', hata.message);
            return null;
        }
        
        // Beklenmedik hatalar
        console.error('Beklenmedik hata:', hata);
        throw hata; // Üst seviyeye ilet
    }
}
 
// Kullanım
async function kullan() {
    let sonuc = await guvenliVeriAl(999);
    if (sonuc) {
        console.log('Veri alındı:', sonuc);
    } else {
        console.log('Veri alınamadı');
    }
}

Fetch API (HTTP İstekleri)

Temel Fetch Kullanımı

// GET isteği
async function kullaniciListesiAl() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/users');
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        let kullanicilar = await response.json();
        console.log('Kullanıcılar:', kullanicilar);
        return kullanicilar;
    } catch (hata) {
        console.error('Kullanıcı listesi alırken hata:', hata);
    }
}
 
// POST isteği
async function kullaniciOlustur(kullaniciVerisi) {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/users', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(kullaniciVerisi)
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        let yeniKullanici = await response.json();
        console.log('Yeni kullanıcı oluşturuldu:', yeniKullanici);
        return yeniKullanici;
    } catch (hata) {
        console.error('Kullanıcı oluştururken hata:', hata);
    }
}
 
// Kullanım
kullaniciOlustur({
    name: 'Furkan Çelik',
    email: '[email protected]',
    phone: '0555-123-4567'
});

Gelişmiş Fetch Konfigürasyonu

// Timeout ile
async function timeoutFetch(url, options = {}, timeout = 5000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    
    try {
        const response = await fetch(url, {
            ...options,
            signal: controller.signal
        });
        clearTimeout(timeoutId);
        return response;
    } catch (error) {
        clearTimeout(timeoutId);
        if (error.name === 'AbortError') {
            throw new Error('Request timeout');
        }
        throw error;
    }
}
 
// Auth header ile
async function authFetch(url, token, options = {}) {
    return fetch(url, {
        ...options,
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json',
            ...options.headers
        }
    });
}
 
// Retry mekanizması ile
async function retryFetch(url, options = {}, maxRetries = 3) {
    for (let i = 0; i <= maxRetries; i++) {
        try {
            const response = await fetch(url, options);
            if (response.ok) return response;
            
            if (i === maxRetries) {
                throw new Error(`Failed after ${maxRetries} retries`);
            }
        } catch (error) {
            if (i === maxRetries) throw error;
            
            // Exponential backoff
            await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
        }
    }
}

Modern JavaScript Özellikleri

Template Literals ve Tagged Templates

// Temel template literal
let isim = 'Furkan';
let yas = 25;
let mesaj = `Merhaba, ben ${isim} ve ${yas} yaşındayım.`;
 
// Çok satırlı
let htmlSablon = `
    <div class="card">
        <h3>${isim}</h3>
        <p>Yaş: ${yas}</p>
        <p>Durum: ${yas >= 18 ? 'Yetişkin' : 'Çocuk'}</p>
    </div>
`;
 
// Tagged templates
function highlight(strings, ...values) {
    return strings.reduce((result, string, i) => {
        const value = values[i] ? `<strong>${values[i]}</strong>` : '';
        return result + string + value;
    }, '');
}
 
let vurguluMesaj = highlight`Merhaba ${isim}, yaşın ${yas}`;
console.log(vurguluMesaj); // Merhaba <strong>Furkan</strong>, yaşın <strong>25</strong>

Destructuring Assignment

// Array destructuring
let renkler = ['kırmızı', 'yeşil', 'mavi', 'sarı'];
let [ilk, ikinci, ...geriKalan] = renkler;
console.log(ilk);        // 'kırmızı'
console.log(geriKalan);  // ['mavi', 'sarı']
 
// Object destructuring
let kullanici = {
    isim: 'Furkan',
    yas: 25,
    email: '[email protected]',
    adres: {
        sehir: 'İstanbul',
        ilce: 'Kadıköy'
    }
};
 
let {isim, yas, email, adres: {sehir}} = kullanici;
console.log(isim, yas, sehir); // 'Furkan' 25 'İstanbul'
 
// Varsayılan değerler
let {telefon = 'Belirtilmemiş'} = kullanici;
console.log(telefon); // 'Belirtilmemiş'
 
// Yeniden adlandırma
let {isim: kullaniciAdi, yas: kullaniciYasi} = kullanici;
console.log(kullaniciAdi); // 'Furkan'

Spread ve Rest Operatörleri

// Spread operatörü (...)
let sayilar1 = [1, 2, 3];
let sayilar2 = [4, 5, 6];
let birlesik = [...sayilar1, ...sayilar2]; // [1, 2, 3, 4, 5, 6]
 
// Obje spread
let temelBilgi = {isim: 'Furkan', yas: 25};
let tamBilgi = {...temelBilgi, email: '[email protected]', sehir: 'İstanbul'};
 
// Function arguments
function toplam(...sayilar) {
    return sayilar.reduce((sum, num) => sum + num, 0);
}
console.log(toplam(1, 2, 3, 4, 5)); // 15
 
// Rest in destructuring
let [birinci, ...kalanlar] = [1, 2, 3, 4, 5];
console.log(birinci);  // 1
console.log(kalanlar); // [2, 3, 4, 5]

Arrow Functions ve Lexical This

// Traditional function vs Arrow function
let obje = {
    isim: 'Test',
    
    // Traditional - kendi this'i var
    geleneksel: function() {
        console.log('Geleneksel:', this.isim); // 'Test'
        
        setTimeout(function() {
            console.log('Timeout geleneksel:', this.isim); // undefined (window.isim)
        }, 1000);
    },
    
    // Arrow - üst scope'un this'ini kullanır
    arrow: function() {
        console.log('Arrow dış:', this.isim); // 'Test'
        
        setTimeout(() => {
            console.log('Timeout arrow:', this.isim); // 'Test'
        }, 1000);
    }
};
 
obje.geleneksel();
obje.arrow();

Pratik Örnekler

Hava Durumu Uygulaması

class HavaDurumuApp {
    constructor() {
        this.apiKey = 'YOUR_API_KEY'; // OpenWeatherMap API key
        this.baseUrl = 'https://api.openweathermap.org/data/2.5';
        this.init();
    }
    
    init() {
        this.createHTML();
        this.bindEvents();
    }
    
    createHTML() {
        document.body.innerHTML = `
            <div class="weather-app">
                <h1>Hava Durumu</h1>
                <div class="search-container">
                    <input type="text" id="cityInput" placeholder="Şehir adı girin...">
                    <button id="searchBtn">Ara</button>
                    <button id="locationBtn">Konumum</button>
                </div>
                <div id="loading" class="loading hidden">Yükleniyor...</div>
                <div id="weatherInfo" class="weather-info hidden"></div>
                <div id="forecast" class="forecast hidden"></div>
                <div id="error" class="error hidden"></div>
            </div>
        `;
        
        this.addStyles();
    }
    
    addStyles() {
        let style = document.createElement('style');
        style.textContent = `
            .weather-app { max-width: 600px; margin: 50px auto; padding: 20px; }
            .search-container { display: flex; gap: 10px; margin-bottom: 20px; }
            #cityInput { flex: 1; padding: 10px; }
            button { padding: 10px 15px; cursor: pointer; }
            .weather-info { background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; }
            .forecast { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
            .forecast-item { background: #e9ecef; padding: 15px; border-radius: 5px; text-align: center; }
            .hidden { display: none; }
            .loading { text-align: center; padding: 20px; }
            .error { background: #f8d7da; color: #721c24; padding: 15px; border-radius: 5px; }
        `;
        document.head.appendChild(style);
    }
    
    bindEvents() {
        let searchBtn = document.getElementById('searchBtn');
        let locationBtn = document.getElementById('locationBtn');
        let cityInput = document.getElementById('cityInput');
        
        searchBtn.addEventListener('click', () => this.searchByCity());
        locationBtn.addEventListener('click', () => this.searchByLocation());
        
        cityInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') this.searchByCity();
        });
    }
    
    async searchByCity() {
        let city = document.getElementById('cityInput').value.trim();
        if (!city) return;
        
        try {
            this.showLoading();
            let weatherData = await this.getWeatherByCity(city);
            let forecastData = await this.getForecastByCity(city);
            this.displayWeather(weatherData, forecastData);
        } catch (error) {
            this.showError('Şehir bulunamadı: ' + error.message);
        }
    }
    
    async searchByLocation() {
        try {
            this.showLoading();
            let position = await this.getCurrentPosition();
            let {latitude, longitude} = position.coords;
            
            let weatherData = await this.getWeatherByCoords(latitude, longitude);
            let forecastData = await this.getForecastByCoords(latitude, longitude);
            this.displayWeather(weatherData, forecastData);
        } catch (error) {
            this.showError('Konum alınamadı: ' + error.message);
        }
    }
    
    getCurrentPosition() {
        return new Promise((resolve, reject) => {
            if (!navigator.geolocation) {
                reject(new Error('Geolocation desteklenmiyor'));
                return;
            }
            
            navigator.geolocation.getCurrentPosition(resolve, reject);
        });
    }
    
    async getWeatherByCity(city) {
        let response = await fetch(
            `${this.baseUrl}/weather?q=${city}&appid=${this.apiKey}&units=metric&lang=tr`
        );
        
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        
        return await response.json();
    }
    
    async getForecastByCity(city) {
        let response = await fetch(
            `${this.baseUrl}/forecast?q=${city}&appid=${this.apiKey}&units=metric&lang=tr`
        );
        
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        
        return await response.json();
    }
    
    async getWeatherByCoords(lat, lon) {
        let response = await fetch(
            `${this.baseUrl}/weather?lat=${lat}&lon=${lon}&appid=${this.apiKey}&units=metric&lang=tr`
        );
        
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        
        return await response.json();
    }
    
    async getForecastByCoords(lat, lon) {
        let response = await fetch(
            `${this.baseUrl}/forecast?lat=${lat}&lon=${lon}&appid=${this.apiKey}&units=metric&lang=tr`
        );
        
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        
        return await response.json();
    }
    
    displayWeather(current, forecast) {
        this.hideLoading();
        
        // Güncel hava durumu
        let weatherInfo = document.getElementById('weatherInfo');
        weatherInfo.innerHTML = `
            <h2>${current.name}, ${current.sys.country}</h2>
            <div style="display: flex; align-items: center; gap: 20px;">
                <img src="https://openweathermap.org/img/w/${current.weather[0].icon}.png" alt="${current.weather[0].description}">
                <div>
                    <div style="font-size: 2em; font-weight: bold;">${Math.round(current.main.temp)}°C</div>
                    <div>${current.weather[0].description}</div>
                </div>
            </div>
            <div style="margin-top: 15px; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;">
                <div>Hissedilen: ${Math.round(current.main.feels_like)}°C</div>
                <div>Nem: ${current.main.humidity}%</div>
                <div>Rüzgar: ${current.wind.speed} m/s</div>
                <div>Basınç: ${current.main.pressure} hPa</div>
            </div>
        `;
        weatherInfo.classList.remove('hidden');
        
        // 5 günlük tahmin
        let forecastContainer = document.getElementById('forecast');
        let dailyForecasts = this.processForecastData(forecast);
        
        forecastContainer.innerHTML = dailyForecasts.map(day => `
            <div class="forecast-item">
                <div style="font-weight: bold;">${day.date}</div>
                <img src="https://openweathermap.org/img/w/${day.icon}.png" alt="${day.description}">
                <div>${Math.round(day.temp)}°C</div>
                <div style="font-size: 0.9em;">${day.description}</div>
            </div>
        `).join('');
        forecastContainer.classList.remove('hidden');
    }
    
    processForecastData(forecast) {
        let dailyData = {};
        
        forecast.list.forEach(item => {
            let date = new Date(item.dt * 1000);
            let day = date.toLocaleDateString('tr-TR', {weekday: 'short', day: 'numeric'});
            
            if (!dailyData[day]) {
                dailyData[day] = {
                    date: day,
                    temp: item.main.temp,
                    icon: item.weather[0].icon,
                    description: item.weather[0].description
                };
            }
        });
        
        return Object.values(dailyData).slice(0, 5);
    }
    
    showLoading() {
        document.getElementById('loading').classList.remove('hidden');
        document.getElementById('weatherInfo').classList.add('hidden');
        document.getElementById('forecast').classList.add('hidden');
        document.getElementById('error').classList.add('hidden');
    }
    
    hideLoading() {
        document.getElementById('loading').classList.add('hidden');
    }
    
    showError(message) {
        this.hideLoading();
        let errorDiv = document.getElementById('error');
        errorDiv.textContent = message;
        errorDiv.classList.remove('hidden');
        
        document.getElementById('weatherInfo').classList.add('hidden');
        document.getElementById('forecast').classList.add('hidden');
    }
}
 
// Demo için mock versiyon (API key gerekmez)
class MockHavaDurumuApp extends HavaDurumuApp {
    async getWeatherByCity(city) {
        // Simulate API delay
        await new Promise(resolve => setTimeout(resolve, 1000));
        
        return {
            name: city,
            sys: {country: 'TR'},
            main: {
                temp: 22,
                feels_like: 24,
                humidity: 65,
                pressure: 1013
            },
            weather: [{
                icon: '01d',
                description: 'açık hava'
            }],
            wind: {speed: 3.2}
        };
    }
    
    async getForecastByCity(city) {
        await new Promise(resolve => setTimeout(resolve, 500));
        
        return {
            list: Array.from({length: 40}, (_, i) => ({
                dt: Date.now() / 1000 + (i * 3 * 60 * 60), // 3 hour intervals
                main: {temp: 20 + Math.random() * 10},
                weather: [{
                    icon: '01d',
                    description: 'güneşli'
                }]
            }))
        };
    }
}
 
// Uygulamayı başlat
new MockHavaDurumuApp();

Pratik Egzersizler

Egzersiz 1: RESTful API Client

class ApiClient {
    constructor(baseUrl) {
        this.baseUrl = baseUrl;
    }
    
    // Tüm HTTP metodları için generic fetch wrapper
    async request(endpoint, options = {}) {
        // 1. URL oluşturma
        // 2. Headers yönetimi
        // 3. Error handling
        // 4. Response parsing
        // 5. Retry logic
    }
    
    // CRUD operasyonları
    async get(endpoint) { /* GET isteği */ }
    async post(endpoint, data) { /* POST isteği */ }
    async put(endpoint, data) { /* PUT isteği */ }
    async delete(endpoint) { /* DELETE isteği */ }
}

Egzersiz 2: Real-time Chat Simulator

class ChatApp {
    constructor() {
        this.messages = [];
        this.users = [];
        this.currentUser = null;
    }
    
    // WebSocket simulation with async/await
    async sendMessage(message) {
        // 1. Message validation
        // 2. Async send simulation
        // 3. Real-time update
        // 4. Error handling
    }
    
    async receiveMessages() {
        // 1. Long polling simulation
        // 2. Message parsing
        // 3. UI update
    }
}

Egzersiz 3: Progressive Image Loader

class ImageLoader {
    constructor() {
        this.loadQueue = [];
        this.loading = false;
    }
    
    async loadImage(src) {
        // 1. Progressive loading
        // 2. Lazy loading
        // 3. Placeholder handling
        // 4. Error recovery
    }
    
    async loadImagesInBatches(imageUrls, batchSize = 3) {
        // 1. Batch processing
        // 2. Concurrency control
        // 3. Progress tracking
    }
}
Ipucu

Best Practice: async/await kullanırken her zaman try-catch ile error handling yapın. Promise.all kullanırken biri başarısız olursa hepsinin başarısız olacağını unutmayın.

Seri Tamamlandı! 🎉

Tebrikler! JavaScript eğitim serisini tamamladınız. Artık modern JavaScript ile:

Öğrendikleriniz:

  • ✅ Asenkron programlama temelleri
  • ✅ Promise ve async/await kullanımı
  • ✅ Fetch API ile HTTP istekleri
  • ✅ Modern JavaScript özellikleri (ES6+)
  • ✅ Error handling ve best practices
  • ✅ Gerçek dünya projeleri geliştirme

Sıradaki Adımlar:

  1. Framework’ler: React, Vue.js veya Angular öğrenin
  2. Node.js: Backend geliştirme için JavaScript
  3. TypeScript: Tip güvenliği için
  4. Build Tools: Webpack, Vite, Parcel
  5. Testing: Jest, Cypress ile test yazma

JavaScript yolculuğunuz daha yeni başlıyor! Pratik yapın, projeler geliştirin ve JavaScript ekosistemini keşfetmeye devam edin. 🚀