From ceff499ee0e8d45f25fb2f61c5b7a16669b39500 Mon Sep 17 00:00:00 2001 From: Matteo Basso Date: Mon, 18 Jul 2016 19:05:51 +0200 Subject: [PATCH] Add refractionLevel --- docs/api/Subscribe.md | 2 ++ docs/basics/Subscribing.md | 28 +++++++++++++++++++++++++++- package.json | 2 +- src/Mediator.js | 3 ++- src/index.js | 16 +++++++++++++++- test/index.spec.js | 28 ++++++++++++++++++++++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/docs/api/Subscribe.md b/docs/api/Subscribe.md index 993766e..50ac2c3 100644 --- a/docs/api/Subscribe.md +++ b/docs/api/Subscribe.md @@ -14,7 +14,9 @@ Subscribe the given object to events. ```js // subscribe to 'newChatPartecipant' channel +// set priority to 90 (default 100) const subscriber = { + refractionLevel: 90, newChatPartecipant: (payload) => { const { username } = payload; alert(`Hi ${username}!`); diff --git a/docs/basics/Subscribing.md b/docs/basics/Subscribing.md index 5055158..4b2420b 100644 --- a/docs/basics/Subscribing.md +++ b/docs/basics/Subscribing.md @@ -33,7 +33,33 @@ unsubscribeFunction(); If you delete a subscriber making it null, Refraction will unsubscribe it for you during next publishing. -When we declare a subscriber is important to keep in mind that events will be published in a synchronous way, Refraction will notify that an event is fired after that the previous subscriber has finished his execution. For this reason subscriber might have small functions and might be a little number. However if you have a lot of subscriber on a single channel, or if you want to do some stuff asynchronously, you can put a setTimeout with 0 offset, for example, in your handler. This will execute your code asynchronously and Refraction will step over, having better performance. Here is a little example: +When we declare a subscriber is important to keep in mind that events will be published in a synchronous way, Refraction will notify that an event is fired after that the previous subscriber has finished his execution. For this reason, you can set a level to each subscriber, to determine the order of execution. A lower level indicates that the subscriber have to be executed earlier, so, an higher level indicates that the subscriber have to be executed later. Level can be specified with a prop `refractionLevel` in the subscriber, that, by default is 100. Here is an example: + +```js +let i = 0; +const secondSubscriber = { + // by default refractionLevel: 100, + foo: () => { + // i = 1 + i += 1; + // i = 2 + } +}; +const firstSubscriber = { + refractionLevel: 90, + foo: () => { + // i = 0 + i += 1; + // i = 1 + } +}; +// subscribing order will be ignored, refractionLevel is evaluated instead +refractionInstance.subscribe(secondSubscriber); +refractionInstance.subscribe(firstSubscriber); +refractionInstance.publish('foo'); +``` + +Consider also that subscribers might have small functions and might be a little number. However if you have a lot of subscriber on a single channel, or if you want to do some stuff asynchronously, you can put a setTimeout with 0 offset, for example, in your handler. This will execute your code asynchronously and Refraction will step over, having better performance. Here is a little example: ```js const subscriber = { diff --git a/package.json b/package.json index e1fcabe..0ea6659 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "refraction", - "version": "1.1.0", + "version": "1.2.0", "description": "A guard that represent central point of control in your application.", "main": "lib/index.js", "jsnext:main": "es/index.js", diff --git a/src/Mediator.js b/src/Mediator.js index 5927b4b..8433b80 100644 --- a/src/Mediator.js +++ b/src/Mediator.js @@ -2,9 +2,10 @@ export default class Mediator { subscribers = []; - subscribe(subscriber) { + subscribe(subscriber, compareFunction) { if (this.subscribers.indexOf(subscriber) === -1) { this.subscribers.push(subscriber); + this.subscribers.sort(compareFunction); } } diff --git a/src/index.js b/src/index.js index 23edfc5..59089eb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,20 @@ import Mediator from './Mediator'; import History from './History'; +const getSubscriberLevel = (subscriber) => subscriber.refractionLevel || 100; + +const compareFunction = (a, b) => { + let result = 0; + const aPriority = getSubscriberLevel(a); + const bPriority = getSubscriberLevel(b); + if (aPriority < bPriority) { + result = -1; + } else if (aPriority > bPriority) { + result = 1; + } + return result; +}; + export default class Refraction { middlewares = []; @@ -30,7 +44,7 @@ export default class Refraction { } subscribe(subscriber) { - this.mediator.subscribe(subscriber); + this.mediator.subscribe(subscriber, compareFunction); return this.unsubscribe.bind(this, subscriber); } diff --git a/test/index.spec.js b/test/index.spec.js index fb4f4d8..9785d11 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -68,6 +68,34 @@ describe('Refraction', () => { expect(refraction.mediator.subscribers).toEqual([]); }); + it('should subscribe with level', (done) => { + let i = 0; + const foo = { + refractionLevel: 90, + onTest: () => { + expect(i).toEqual(0); + i++; + }, + }; + const bar = { + onTest: () => { + expect(i).toEqual(1); + i++; + }, + }; + const lorem = { + refractionLevel: 110, + onTest: () => { + expect(i).toEqual(2); + done(); + }, + }; + refraction.subscribe(lorem); + refraction.subscribe(foo); + refraction.subscribe(bar); + refraction.publish('onTest'); + }); + it('should unsubscribe', () => { const unknownSubscriber = { onFail: () => false }; refraction.subscribe(subscriber);