Giter Site home page Giter Site logo

sarvex / mediator_lua Goto Github PK

View Code? Open in Web Editor NEW

This project forked from luadist/mediator_lua

0.0 2.0 0.0 146 KB

Mediator pattern implementation for pub-sub management

Home Page: http://www.olivinelabs.com/mediator_lua

CMake 72.44% Lua 27.56%

mediator_lua's Introduction

mediator_lua

Version 1.0

For more information, please see

View the project on Github

View the documentation

If you have luarocks, isntall it with luarocks install mediator_lua. If you don't, get it. If you really don't want to, just copy mediator.lua from the Git repository.

A utility class to help you manage events.

mediator_lua is a simple class that allows you to listen to events by subscribing to and sending data to channels. Its purpose is to help you decouple code where you might otherwise have functions calling functions calling functions, and instead simply call mediator.publish("chat", { message = "hi" })

Why?

My specific use case: manage HTTP routes called in OpenResty. There's an excellent article that talks about the Mediator pattern (in Javascript) in more in detail by Addy Osmani (that made me go back and refactor this code a bit.)

Usage

You can register events with the mediator two ways: using channels, or with a predicate to perform more complex matching (a predicate is a function that returns a true/false value that determines if mediator should run the callback.)

Instantiate a new mediator, and then you can being subscribing, removing, and publishing.

Example:

Mediator = require "mediator_lua"
mediator = Mediator() -- instantiate a new mediator

mediator:publish(channel, <data, data, ... >)
mediator:remove(<channel>) 

Subscription signature:

(channel, callback, <options>, <context>);

Callback signature:

function(<data, data ...>, channel);

Mediator:subscribe options (all are optional; default is empty):

{
  predicate = function(arg1, arg2) return arg1 == arg2 end
  priority = 0|1|... (array index; max of callback array length, min of 0)
}

When you call subscribe, you get a subscriber object back that you can use to update and change options. It looks like:

{
  id, -- unique identifier
  fn, -- function you passed in
  options, -- options
  context, -- context for fn to be called within
  channel, -- provides a pointer back to its channel
  update(options) -- function that accepts { fn, options, context }
}

Examples:

Mediator = require("mediator_lua")
local mediator = Mediator()

-- Print data when the "message" channel is published to
-- Subscribe returns a "Subscriber" object
mediator:subscribe({ "message" }, function(data) print(data) end);
mediator:publish({ "message" }, "Hello, world");

  >> Hello, world

-- Print the message when the predicate function returns true
local predicate = function(data) 
  return data.From == "Jack" 
end

mediator.Subscribe({ "channel" }, function(data) print(data.Message) end, { predicate = predicate });
mediator.Publish({ "channel" }, { Message = "Hey!", From = "Jack" })
mediator.Publish({ "channel" }, { Message = "Hey!", From = "Drew" })

  >> Hey!

You can remove events by passing in a type or predicate, and optionally the function to remove.

-- removes all methods bound to a channel 
mediator:remove({ "channel" })

-- unregisters MethodFN, a named function we defined elsewhere, from "channel" 
mediator:remove({ "channel" }, MethodFN)

You can call the registered functions with the publish method, which accepts an args array:

mediator:publish({ "channel" }, "argument", "another one", { etc: true }); # args go on forever

You can namespace your subscribing / removing / publishing. This will recurisevely call children, and also subscribers to direct parents.

mediator:subscribe({ "application:chat:receiveMessage" }, function(data){ ... })

-- will recursively call anything in the appllication:chat:receiveMessage namespace 
-- will also call thins directly subscribed to application and application:chat,
-- but not their children
mediator:publish({ "application", "chat", "receiveMessage" }, "Jack Lawson", "Hey")

-- will recursively remove everything under application:chat
mediator:remove({ "application", "chat" })

You can update Subscriber priority:

local sub = mediator:subscribe({ "application", "chat" }, function(data){ ... })
local sub2 = mediator:subscribe({ "application", "chat" }, function(data){ ... })

-- have sub2 executed first
mediator.GetChannel({ "application", "chat" }).SetPriority(sub2.id, 0);

You can update Subscriber callback, context, and/or options:

sub:update({ fn: ..., context = { }, options = { ... })

You can stop the chain of execution by calling channel:stopPropagation()

-- for example, let's not post the message if the `from` and `to` are the same
mediator.Subscribe({ "application", "chat" }, function(data, channel) 
  -- throw an error message or something
  channel:stopPropagation()
end, options = {
  predicate = function(data) return data.From == data.To end,
  priority = 0
})

Testing

Uses lunit for testing; you can install it through luarocks.

Contributing

Build stuff, run the tests, then submit a pull request with comments and a description of what you've done, and why.

License

This code and its accompanying README and are MIT licensed.

In Closing

Have fun, and please submit suggestions and improvements! You can leave any issues here, or contact me on Twitter (@ajacksified).

mediator_lua's People

Contributors

ajacksified avatar doriangray avatar kapecp avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.