TuZaKK 1
TuZaKK
Mt2Hizmet 1
Mt2Hizmet
Agora Metin2 1
Agora Metin2
Bvural41 1
Bvural41
kaptanmikro1 1
kaptanmikro1
R 1
Roksam
[DEV]AB 1
[DEV]AB
Sevdamsın 1
Sevdamsın
farkmt2official 1
farkmt2official
emirhanHCL 1
emirhanHCL
Scarlet 1
Scarlet
Hikaye Ekle

[NODE JS] Promise.race ile Ilk Cevabi Alma

  • Konuyu başlatan Konuyu başlatan Silverhand
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 1
  • Görüntüleme Görüntüleme 12

Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!

nodejs.png


[NODE JS] Promise.race ile Ilk Cevabi Alma​


Merhaba arkadaslar, bugun Promise.race fonksiyonunu inceleyecegiz. Bu fonksiyon, verilen Promise'lerden hangisi ilk sonuclanirsa onun sonucunu dondurur. Diger Promise'ler arka planda calismaya devam eder ama sonuclari yok sayilir. Bunu bir yaris gibi dusunun: hangi Promise birinci gelirse o kazanir.

Promise.race Nasil Calisir?​


Promise.race bir Promise dizisi alir ve ilk resolve veya reject olan Promise'in sonucunu dondurur. Dikkat edin: ilk tamamlanan, basarili olsun ya da olmasin. Yani ilk tamamlanan Promise reject olursa, race de reject olur. Bu davranis bazen kafa karistirabilir ama mantikli dusununce anlamli.

Ben bu fonksiyonu en cok timeout mekanizmasi icin kullaniyorum. Bir API cagrisina belirli bir sure limiti koymak istediginizde, API cagrisini ve bir timeout Promise'ini race ettirirsiniz. Hangisi once sonuclanirsa o kazanir. API cevap vermezse timeout kazanir ve siz hata alirsiniz.

JavaScript:
// Temel Promise.race kullanimi
const hizli = new Promise(resolve => setTimeout(() => resolve('Hizli kazandi!'), 100));
const yavas = new Promise(resolve => setTimeout(() => resolve('Yavas geldi'), 500));

Promise.race([hizli, yavas])
    .then(sonuc => {
        console.log(sonuc); // "Hizli kazandi!"
    });

// Timeout mekanizmasi
function timeoutIle(promise, limitMs) {
    const timeout = new Promise((_, reject) => {
        setTimeout(() => {
            reject(new Error(`Islem ${limitMs}ms icinde tamamlanamadi`));
        }, limitMs);
    });

    return Promise.race([promise, timeout]);
}

// Kullanim
async function veriCek() {
    try {
        // 200ms surec bir islemi 150ms timeout ile dene
        const sonuc = await timeoutIle(
            new Promise(resolve => setTimeout(() => resolve('Veri geldi'), 200)),
            150
        );
        console.log(sonuc);
    } catch (hata) {
        console.error('Timeout:', hata.message);
    }
}

veriCek();

// Birden fazla kaynaktan en hizli cevabi al
async function enHizliKaynaktanAl() {
    const kaynaklar = [
        new Promise(resolve => {
            setTimeout(() => resolve({ kaynak: 'API-1', veri: 'Turkiye' }), 300);
        }),
        new Promise(resolve => {
            setTimeout(() => resolve({ kaynak: 'API-2', veri: 'Turkiye' }), 100);
        }),
        new Promise(resolve => {
            setTimeout(() => resolve({ kaynak: 'API-3', veri: 'Turkiye' }), 200);
        })
    ];

    const sonuc = await Promise.race(kaynaklar);
    console.log(`En hizli kaynak: ${sonuc.kaynak}`);
    return sonuc;
}

enHizliKaynaktanAl();

Gercek Hayat Ornekleri​


Promise.race'in en pratik kullanim alanlari timeout mekanizmasi, fallback stratejisi ve kullanici etkilesimi kontrolu. Ben production'da en cok timeout icin kullaniyorum. Ozellikle dis servislere yapilan isteklerde, cevabin belirli bir sure icinde gelip gelmedigini kontrol etmek icin mukemmel bir arac.

Bir diger guzel kullanim alani da health check yapmak. Birden fazla sunucuya ayni anda istek gonderip hangisinin ilk cevap verdigini bulabilirsiniz. Bu sayede en hizli sunucuyu otomatik olarak secebilirsiniz. Ben bunu load balancer benzeri bir yapilanma icin kullanmistim ve cok guzel calismisti.

JavaScript:
// Gelismis timeout wrapper
function timeoutluIslem(islemAdi, promise, limitMs) {
    let timeoutId;

    const timeout = new Promise((_, reject) => {
        timeoutId = setTimeout(() => {
            reject(new Error(
                `"${islemAdi}" islemi ${limitMs}ms zaman asimina ugradi`
            ));
        }, limitMs);
    });

    return Promise.race([promise, timeout]).finally(() => {
        clearTimeout(timeoutId); // Temizlik
    });
}

// HTTP istegi simulasyonu
function httpIstegi(url, gecikmeMs) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.1) {
                resolve({ url, status: 200, veri: 'basarili' });
            } else {
                reject(new Error(`${url} - baglanti hatasi`));
            }
        }, gecikmeMs);
    });
}

// Health check
async function healthCheck(sunucular) {
    console.log('\n=== Health Check ===');

    const kontrolSonuclari = await Promise.allSettled(
        sunucular.map(sunucu =>
            timeoutluIslem(
                sunucu.ad,
                httpIstegi(sunucu.url, sunucu.beklenenSure),
                1000  // 1 saniye timeout
            )
        )
    );

    kontrolSonuclari.forEach((sonuc, i) => {
        const sunucu = sunucular[i];
        if (sonuc.status === 'fulfilled') {
            console.log(`  ${sunucu.ad}: AKTIF`);
        } else {
            console.log(`  ${sunucu.ad}: PASIF - ${sonuc.reason.message}`);
        }
    });
}

// Kullanici bekleme ekrani - ya veri gelir ya kullanici iptal eder
function kullaniciIptalEdebilir(veriPromise) {
    let iptalFn;
    const iptalPromise = new Promise((_, reject) => {
        iptalFn = () => reject(new Error('Kullanici tarafindan iptal edildi'));
    });

    const sonucPromise = Promise.race([veriPromise, iptalPromise]);

    return { sonuc: sonucPromise, iptal: iptalFn };
}

// Kullanim
async function main() {
    const sunucular = [
        { ad: 'Ana Sunucu', url: 'https://api1.example.com', beklenenSure: 200 },
        { ad: 'Yedek Sunucu', url: 'https://api2.example.com', beklenenSure: 500 },
        { ad: 'CDN Sunucu', url: 'https://cdn.example.com', beklenenSure: 100 }
    ];

    await healthCheck(sunucular);

    // Timeout ornegi
    try {
        const sonuc = await timeoutluIslem(
            'API Cagrisi',
            httpIstegi('https://api.example.com', 2000),
            1000
        );
        console.log('\nSonuc:', sonuc);
    } catch (hata) {
        console.log('\n' + hata.message);
    }
}

main().catch(console.error);

Dikkat Edilmesi Gerekenler​


Promise.race kullanirken unutmamn gereken en onemli sey, kaybeden Promise'lerin hala calismaya devam etmesidir. Race sadece sonucu yok sayar, islemi iptal etmez. Yani 5 API cagrisi yaptiniz ve birincisi hemen cevap verdi, diger 4'u hala sunucuya istek atiyor olacak. Bu gereksiz kaynak tuketimi anlamina gelir. Bunu AbortController ile cozebilirsiniz ama bu baska bir konunun meselesi.

Diger onemli nokta, bos diziyle cagirirsaniz Promise.race sonsuza kadar pending kalir, hicbir zaman resolve veya reject olmaz. Bu bir bug kaynagi olabilir, dizinin bos olmam kontrol edin. Herneyse, sonraki konumuz Promise.any olacak!
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst