Implementace Pub-Sub v JavaScriptu

S dnešním trendy tématem Micro Front Ends je velkou otázkou, jak komunikovat různé MFE? To by mohlo být snadné, pokud používáte stejný rámec ve svých různých projektech, ale pokud zvolíte různé rámce jako:React, Angular nebo VueJS, komunikace a sdílení stavu může být obtížné. Dalším případem použití je, pokud částečně implementujete nový rámec, abyste mohli žít se starším kódem.

V tomto příspěvku se dozvíte, jak komunikovat tyto různé dílčí projekty bez ohledu na to, jaký počet nebo název rámců používáte. Existuje pouze jedno pravidlo:vaše aplikace by se měla chovat jako jednostránková aplikace, což je nejčastější případ použití MFE, takže bychom měli být v dobré kondici.

Nejprve začněme pochopením návrhového vzoru:

Publish-Subscribe je návrhový vzor, ​​kdy odesílatelé (vydavatelé) mohou odesílat zprávy příjemcům (předplatitelům), aniž by předplatitelé věděli, co vydavatelé dělají. A jak nám to může pomoci s komunikací různých projektů? Snadno, budeme mít vydavatele z jednoho projektu a předplatitele v jiném projektu a naopak, což usnadní komunikaci a sdílení zdrojů.

Na následujícím obrázku můžeme vidět znázornění návrhového vzoru, kde:

Máme vydavatele, který může být jako satelitní odesílající signál (odesílatel), přičemž kanály jsou různá témata, k jejichž odběru se mohou předplatitelé přihlásit, a předplatitelé (přijímače), což jsou v příkladu televizory, které budou zprávu přijímat ( hvězdy). Pokud to vidíte takto, můžete interpretovat návrhový vzor a na skutečném případě pochopit, jak to funguje.

Jaký je případ použití?

Vezměme následující obrázek jako projekt, který vytváříme. Nyní si představte, že Team Checkout musí odeslat cenu a položku, která je vybrána po stisknutí Buy for 66,00 € k Team Inspire (což je v tomto případě košík ve vašem projektu eCommerce), rámce jsou odlišné a neexistuje žádný middleware, který by je sděloval. Dokážete identifikovat vydavatele a předplatitele? Skvělé!

Kódování návrhového vzoru

  // topics should only be modified from the eventRouter itself, any violation to the pattern will reflect misbehave
  window.pubSub = (() => {
    const topics = {}
    const hOP = topics.hasOwnProperty

    return {
      publish: (topic, info) => {
        // No topics
        if(!hOP.call(topics, topic)) return

        // Emit the message to any of the receivers
        topics[topic].forEach(item => {
          // Send any arguments if specified
          item(info !== undefined ? info : {})
        })
      },
      subscribe: (topic, callback) => {
        // Create the array of topics if not initialized yet
        if(!hOP.call(topics, topic)) topics[topic] = []

        // We define the index where this receiver is stored in the topics array
        const index = topics[topic].push(callback) - 1

        // When we subscribe we return an object to later remove the subscription
        return {
          remove: () => {
            delete topics[topic][index]
          },
        }
      },
    }
  })()

Příprava našich televizorů na příjem signálu:

  let subscriber1 = pubSub.subscribe('hello', myArg => console.warn('hello', myArg))
  let subscriber2 = pubSub.subscribe('hello', myArg => console.warn('bye', myArg))

Nyní máme odběratele, kteří poslouchají stejnou událost:'hello' kdykoli pošleme zprávu přes tento kanál, tito dva příjemci zprávu vysílají.

  // Executing
  pubSub.publish('hello', 'world')

  // Will output
  "hello world"
  "bye world"

Řekněme, že chceme, aby zprávy od vydavatele nadále sděloval pouze odběratel1, jednoduše:

  // This remove the subscription to the channel/topic we subscribed to
  subscriber1.remove()

A takto snadno můžete komunikovat s různými MFE pomocí vzoru Pub-Sub.

Tento kód byl poprvé viděn na blogu Davida Walshe, čtenáři jej rozšířili a upravili pro vysvětlení a použití MFE v aktuálním projektu, na kterém pracuji.

Děkujeme za přečtení!