İçeriğe geç

Javascript Asenkron döngü örneği

Merhaba,arama motoru projem için örümcek yazdığım sırada karşılaştığım bir performans sorunu vardı. Bende çözüm üretmeye çalışırken sayfalar üzerinde kazdığım linklere gönderdiğim Asenkron http isteklerini senkron bir döngü içinde çalıştırdığı mı fark ettim. Anlayacağınız gidip forEach içinde asenkron bir işlem gerçekleştiriyordum.

Burada ki problem ise şuydu, sistem sürekli yeni bir domain bulduğu ve bulduğu yeni domainler üzerinden de yeni linkler kazdığını ve bu işin ucunun bucağının olmadığı bu sonsuz döngü uçurumunda asenkron olarak çalıştırdığım istek fonksiyonu benim kullandığım döngü tarafından umursanmıyordu.

Örneğin bir sayfada 100 url adresi buldum,şimdi bunlardan istediğim bilgileri almak için tekrar bulduğum bu url adreslerine bir istek gönderiyorum ama döngü senkron olduğu için kullandığım bu fonksiyonun bitmesini beklemeden bu 100 isteği aynı anda gönderiyordu. Bir kaç dakika içinde sistemin kullandığı ram miktarı o kadar büyük bir rakam oluyordu ki tüm yapı buna dayanamayıp çöküyordu. Bende bunu çözebilmek için Asenkron olarak çalışacak bir döngü yazmaya karar verdim ve işe yaradı.

 

Haydi başlayalım

önce direk yazdığım kod parçasını paylaşayım.

function forAsync(tekrar, islem, feedBack) {
    var sayac = 0,bitti = false;
    var For = {
        ilerle: function() {
            if (bitti) {
                return;
            }
            if (sayac < tekrar) {
                sayac++;
                islem(For);
            } else {
                bitti = true;
                feedBack();
            }
        },
        getIndex: function() {
            return sayac - 1;
        },
        break: function() {
            bitti = true;
            feedBack();
        }
    };
    For.ilerle();
    return For;
}

Yukarıda neler yapıyoruz.

function forAsync(tekrar, islem, feedBack) { // Döngü fonksiyonu
    //Döngü kodlarımız
}

forAsync anlayacağınız üzere döngü kodumuz. aldığı parametreler sırası ile aşağıda ki gibidir.

  1. tekrar: İşlemin kaç defa tekrarlanacağı(örneği bir dizinin uzunluğu)
  2. islem:bu parametre bu anonim fonksiyon geriye For adında ki objemizi döndürüyor ,işlem yapmak için tanımladığımız objenin içinde ki fonksiyonları kullanıyoruz.
  3. feedBack: Döngü tamamlandığında aktif hale gelen bir başka anonim fonksiyon.
//Fonksiyon içeriği.
var sayac = 0,bitti = false;
    var For = {
        ilerle: function() {
            if (bitti) {
                return;
            }
            if (sayac < tekrar) {
                sayac++;
                islem(For);
            } else {
                bitti = true;
                feedBack();
            }
        },
        getIndex: function() {
            return sayac - 1;
        },
        break: function() {
            bitti = true;
            feedBack();
        }
    };

Fonksiyonun içeriğine baktığımızda bizi öncelikle iki tane değişken karşılıyor sayac değişkeni anlayacağınız üzere yapılan her ilerlemede bir artıyor. bitti değişkeni ise döngümüzün tamamlanıp tamamlanmadığını belirtiyor ve boolean türünde.

Şimdi For adındaki objenin içeriğini ele alalım.

  1. For.ilerle : Çalıştırıldığında ilk olarak döngünün bitip bitmediğine bakıyor eğer bittiyse fonksiyonu durduruyor,bitmediyse şimdiye kadar kaç işlem yapıldığını toplamda yapılması gereken işlem ile karşılaştırıyor. Eğer yapılması gereken işlem sayısı yapılan işlem sayısından küçükse döngüyü ilerletiyor.(sayac değişkeni bir artıyor). Eğer yapılan işlem sayısı yapılması gerekenden büyükse döngünün bittiği belirtiliyor ve feedBack fonksiyonu çalıştırılıyor.
  2. For.getIndex : Biz çalıştırıldığında döngümüzün kaçıncı indis değerinde olduğunu gösteriyor.
  3. For.break : For döngüsünde alıştığımız break komutu ile aynı işi yapıyor. Çalıştırıldığında döngünün bittiğini söylüyor ve feedBack fonksiyonu çağırılıyor.

Bir örnek ile kullanalım.

/** forAsync fonksiyonu buralarda bir yerde 🙂 **/

var dizi=['Bora Erdinç Özer','Berkehan bendivar','Bul7.com','Boraozer.com','Osman emmi'];
forAsync(dizi.length,function(dongu){
  console.log(dongu.getIndex(),dizi[dongu.getIndex()]);
  dongu.ilerle();
},function(){
  console.log('Dizi okuma işlemi bitti.');
});

Kullanımı  da gördüğünüz üzere gayet basit. Tabi bu fonksiyonu asenkron fonksiyonlarla kullanmanız daha mantıklı. Basit senkron işler için pek gereği yok 🙂

İlk Yorumu Siz Yapın

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir