JavaScript’te Yayınlama/Abone Olma Modeli – JSManifest

JavaScript'te Yayınlama/Abone Olma Modeli – JSManifest

Bu makalede, JavaScript’teki yayınlama/abone olma modelini gözden geçireceğiz ve JavaScript uygulamalarımızda uygulamanın ne kadar basit (ama güçlü) olduğunu göreceğiz.

Yayıncı/abone kalıbı, doğrudan birbirine bağımlı olmadan birbirleriyle iletişim kurabilen modüller ile güçlü dinamik uygulamalar oluşturmamızı sağlayan bir tasarım kalıbıdır.

Desen, JavaScript’te oldukça yaygındır ve şuna çok benzer: gözlemci kalıbı çalışma biçiminde, ancak gözlemci modelinde, bir gözlemci tarafından doğrudan bildirilir. ders yayıncı/abonede ise abone, yayıncı ile abone arasında oturan ve mesajları ileri geri ileten bir kanal aracılığıyla bilgilendirilir.

Bunu uyguladığımızda, bir yayıncıya, aboneye ve abonelerden kaydedilen geri aramaları saklamak için bir yere ihtiyacımız olacak.

Devam edelim ve bunun kodda nasıl göründüğüne bakalım. bir kullanacağız fabrika yayıncı/abone uygulamasını oluşturmak için işlev (bu kalıbı kullanmanız gerekmez).

Yapacağımız ilk şey, abone olunan geri aramaları depolamak için işlev içinde yerel bir değişken bildirmek:

function pubSub() {
  const subscribers = {}
}

Daha sonra, tanımlayacağız subscribe geri aramaları eklemekten sorumlu olacak yöntem subscribers:

function pubSub() {
  const subscribers = {}

  function subscribe(eventName, callback) {
    if (!Array.isArray(subscribers[eventName])) {
      subscribers[eventName] = []
    }
    subscribers[eventName].push(callback)
  }

  return {
    subscribe,
  }
}

Burada olan şey, bir geri arama dinleyicisini kaydetmeye çalışmadan önce etkinlik ismiolup olmadığını kontrol eder. eventName mülk subscribers depolama zaten array. Değilse, bunun için ilk kayıtlı geri arama olacağını varsayar. subscribers[eventName] ve onu bir diziye başlatır. Ardından, geri aramayı diziye göndermeye devam eder.

Ne zaman publish olay patlar, iki argüman alacaktır:

  1. bu eventName
  2. Hiç data bu, * kayıtlı her bir geri aramaya iletilecektir. subscribers[eventName]

Devam edelim ve bunun kodda nasıl göründüğüne bakalım:

function pubSub() {
  const subscribers = {}

  function publish(eventName, data) {
    if (!Array.isArray(subscribers[eventName])) {
      return
    }
    subscribers[eventName].forEach((callback) => {
      callback(data)
    })
  }

  function subscribe(eventName, callback) {
    if (!Array.isArray(subscribers[eventName])) {
      subscribers[eventName] = []
    }
    subscribers[eventName].push(callback)
  }

  return {
    publish,
    subscribe,
  }
}

Geri aramalar listesinde yinelemeden önce subscribersnesnede gerçekten bir dizi olarak var olup olmadığını kontrol edecek ve yoksa, eventName daha önce hiç kayıtlı değildi, bu yüzden sadece geri dönecek. Bu, olası çökmelere karşı bir korumadır. Bundan sonra, program ulaşırsa .forEach satır o zaman biliyoruz ki eventName geçmişte bir veya daha fazla geri arama ile kaydedildi ve döngüye devam ediyor subscribers[eventName] güvenli bir şekilde. Karşılaştığı her geri arama için, geri aramayı data bu ikinci argüman olarak kabul edildi.

Öyleyse, şöyle bir işleve abone olursak:

function showMeTheMoney(money) {
  console.log(money)
}

const ps = pubSub()

ps.subscribe('show-money', showMeTheMoney)

ve ara publish gelecekte bir zaman yöntemi:

ps.publish('show-money', 1000000)

Sonra showMeTheMoney kaydettiğimiz geri arama, almanın yanı sıra çağrılacak 1000000 olarak money argüman:

function showMeTheMoney(money) {
  console.log(money) 
}

Ve yayıncı/abone kalıbı böyle çalışır! bir tanımladık pubSub işlev ve geri aramaları depolayan işleve yerel olarak bir konum sağladı, subscribe geri aramaları kaydetme yöntemi ve publish Herhangi bir veriyle kayıtlı tüm geri aramaları yineleyen ve çağıran yöntem.

Yine de bir sorun daha var. Gerçek bir uygulamada, birçok geri aramaya abone olursak hiç bitmeyen bir bellek sızıntısı yaşayabiliriz ve bu konuda hiçbir şey yapmazsak özellikle israf olur.

O halde en son ihtiyacımız olan şey, abone olunan geri aramaların artık gerekli olmadığında kaldırılmasının bir yoludur. Bu durumda sıklıkla olan şey, bazılarının unsubscribe Yöntem bir yere yerleştirilir. Bunu uygulamak için en uygun yer, dönüş değeri subscribeçünkü bence bunu kodda gördüğümüzde en sezgisel olanı:

function subscribe(eventName, callback) {
  if (!Array.isArray(subscribers[eventName])) {
    subscribers[eventName] = []
  }
  subscribers[eventName].push(callback)
  const index = subscribers[eventName].length - 1

  return {
    unsubscribe() {
      subscribers[eventName].splice(index, 1)
    },
  }
}

const unsubscribe = subscribe('food', function(data) {
  console.log(`Received some food: ${data}`)
})


unsubscribe()

Örnekte, kullandığımızdan beri doğru olanı kaldırdığımızdan emin olmak için bir dizine ihtiyacımız vardı. .splice aradığımız öğeyi kaldırmak için doğru bir dizine ihtiyaç duyan.

Bunun gibi bir şey de yapabilirsiniz, ancak daha az performanslıdır:

function subscribe(eventName, callback) {
  if (!Array.isArray(subscribers[eventName])) {
    subscribers[eventName] = []
  }
  subscribers[eventName].push(callback)
  const index = subscribers[eventName].length - 1

  return {
    unsubscribe() {
      subscribers[eventName] = subscribers[eventName].filter((cb) => {
        
        if (cb === callback) {
          return false
        }
        return true
      })
    },
  }
}

Dezavantajları

Bu modelin çok büyük faydaları olmasına rağmen, bize çok fazla hata ayıklama zamanına mal olabilecek yıkıcı dezavantajlar da vardır. Aynı geri aramaya daha önce abone olup olmadığımızı nasıl bileceğiz? Bir liste aracılığıyla eşlenen bir yardımcı program uygulamadıkça bunu gerçekten anlamanın bir yolu yok, ancak o zaman JavaScript’in daha fazla görev yapmasını sağlamış oluruz.

Bu kalıbı gerçek dünya senaryosunda ne kadar kötüye kullanırsak, kodumuzu korumak da o kadar zorlaşır. Bu modelde geri aramaların ayrıştırılması gerçeği, bunu yapan ve her yerde bunu yapan geri aramalarınız olduğunda her adımı izlemeyi zorlaştırır.

Çözüm

Ve bu yazının sonu burada bitiyor! Umarım bunu değerli bulmuşsunuzdur ve gelecekte daha fazlasını ararsınız!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.