farkmt2official 1
farkmt2official
mannaxxx 1
mannaxxx
Bvural41 1
Bvural41
Agora Metin2 1
Agora Metin2
berkmenoo 1
berkmenoo
Hikaye Ekle

[NODE JS] once ile Tek Seferlik Event Dinleme

nodejs.png


[NODE JS] once ile Tek Seferlik Event Dinleme​


Merhaba arkadaslar, bugun EventEmitter'in once metodunu ve events modulundeki once fonksiyonunu detayli inceleyecegiz. Tek seferlik event dinleme, dusundugunuzden cok daha fazla kullanilir. Baglanti kuruldugunda, ilk veri geldiginde veya bir kerelik kurulum islemlerinde bu pattern hayat kurtaricidir.

emitter.once() Metodu​


once metodu, on metoduyla ayni sekilde calisir ama listener sadece bir kez tetiklenir ve sonra otomatik olarak kaldirilir. Bu sayede manuel olarak removeListener cagirmak zorunda kalmazsiniz. Ben bunu ozellikle "baglanti kuruldu", "hazir" veya "ilk kullanim" gibi bir kerelik olaylar icin kullaniyorum.

JavaScript:
const EventEmitter = require('events');
const { once } = require('events'); // events.once fonksiyonu

// once metodu temel kullanim
const emitter = new EventEmitter();

emitter.once('baglanti', (bilgi) => {
    console.log('Baglanti kuruldu:', bilgi.sunucu);
    // Bu listener otomatik kaldirilir
});

emitter.emit('baglanti', { sunucu: 'db.example.com' }); // Calisir
emitter.emit('baglanti', { sunucu: 'db2.example.com' }); // Calismaz!

console.log('Dinleyici sayisi:', emitter.listenerCount('baglanti')); // 0

// Once ile kurulum paterni
class Uygulama extends EventEmitter {
    constructor() {
        super();
        this.hazirMi = false;

        this.once('hazir', () => {
            this.hazirMi = true;
            console.log('\nUygulama hazir!');
        });
    }

    baslat() {
        // Kurulum islemleri
        setTimeout(() => {
            console.log('Veritabani baglandi');
            console.log('Redis baglandi');
            console.log('Middleware yuklendi');
            this.emit('hazir');
        }, 100);
    }

    islemYap(islem) {
        if (!this.hazirMi) {
            console.log('Uygulama henuz hazir degil!');
            return;
        }
        console.log(`Islem yapiliyor: ${islem}`);
    }
}

const app = new Uygulama();
app.baslat();

events.once() Fonksiyonu - Promise Tabanli​


Node.js 11.13.0 ile birlikte events modulune eklenen once fonksiyonu cok guclu bir arac. Bu fonksiyon bir EventEmitter ve event adi alip Promise dondurur. Promise, event emit edildiginde resolve olur. Bu sayede async/await ile event'leri bekleyebilirsiniz. Ben bunu cok kullaniyorum, ozellikle stream islemlerinde.

JavaScript:
const { once } = require('events');
const EventEmitter = require('events');
const fs = require('fs');
const http = require('http');
const net = require('net');

// events.once ile Promise tabanli bekleme
async function baglantibekle() {
    const emitter = new EventEmitter();

    // 1 saniye sonra event tetikle
    setTimeout(() => {
        emitter.emit('baglandi', { host: 'localhost', port: 5432 });
    }, 1000);

    console.log('Baglanti bekleniyor...');
    const [bilgi] = await once(emitter, 'baglandi');
    console.log('Baglanti kuruldu:', bilgi);
}

baglantibekle();

// Stream ile once kullanimi
async function dosyaYazVeBekle(dosyaYolu, icerik) {
    const stream = fs.createWriteStream(dosyaYolu);

    stream.write(icerik);
    stream.end();

    // Stream kapanana kadar bekle
    await once(stream, 'finish');
    console.log('Dosya basariyla yazildi!');
}

// HTTP sunucusu baslatma
async function sunucuBaslat(port) {
    const sunucu = http.createServer((req, res) => {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('Merhaba!');
    });

    sunucu.listen(port);
    await once(sunucu, 'listening');
    console.log(`Sunucu ${port} portunda dinliyor`);

    return sunucu;
}

// Hata yonetimi ile once
async function guvenliIslem(emitter, basariEvent, hataEvent = 'error') {
    try {
        const sonuc = await once(emitter, basariEvent);
        return { basarili: true, veri: sonuc };
    } catch (error) {
        return { basarili: false, hata: error.message };
    }
}

// AbortController ile timeout
async function timeoutluBekleme(emitter, eventAdi, timeoutMs) {
    const ac = new AbortController();

    const zamanlayici = setTimeout(() => {
        ac.abort();
    }, timeoutMs);

    try {
        const sonuc = await once(emitter, eventAdi, {
            signal: ac.signal
        });
        clearTimeout(zamanlayici);
        return sonuc;
    } catch (error) {
        clearTimeout(zamanlayici);
        if (error.name === 'AbortError') {
            throw new Error(`"${eventAdi}" eventi ${timeoutMs}ms icinde gelmedi`);
        }
        throw error;
    }
}

// Kullanim
async function main() {
    const emitter = new EventEmitter();

    setTimeout(() => emitter.emit('veri', 'test verisi'), 500);

    try {
        const [veri] = await timeoutluBekleme(emitter, 'veri', 1000);
        console.log('\nVeri alindi:', veri);
    } catch (e) {
        console.error(e.message);
    }
}

main().catch(console.error);

Pratik Ipuclari​


once kullanirken dikkat etmeniz gereken noktalar var. events.once fonksiyonu, error event'ini de otomatik olarak dinler. Eger beklediginiz event'ten once bir error event'i emit edilirse, Promise reject olur. Bu davranis cogu zaman istediginiz seydir ama bazen beklenmedik olabilir.

Ayrica once ile uzun sureli bekleme yapiyorsaniz, AbortController ile timeout koymay ihmal etmeyin. Aksi takdirde event hic emit edilmezse, Promise sonsuza kadar pending kalir ve memory leak'e neden olur. Ben bu hataya dustum bir kere, bir WebSocket baglantisinin 'close' event'ini bekliyordum ama baglanti hic kapanmadi ve memory surekli buyudu.

Son tavsiyem: on ile surekli dinleme mi yoksa once ile tek seferlik dinleme mi kullanacaginiza karar verirken, event'in kac kez emit edilecegini dusunun. Bir kerelik olaylar icin her zaman once kullanin, tekrarlayan olaylar icin on kullanin. Bu basit kural sizi bir cok sorundan kurtarir. Siradaki konumuz this baglami!
 

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

Geri
Üst