Comparing version 2.0.1 to 2.0.2
@@ -5,2 +5,12 @@ # Change Log | ||
<a name="2.0.2"></a> | ||
## [2.0.2](https://github.com/vesparny/brcast/compare/v2.0.1...v2.0.2) (2017-07-27) | ||
### Bug Fixes | ||
* prevent handlers unsubscribed in the middle of setState from being called (#5) ([3ad6f58](https://github.com/vesparny/brcast/commit/3ad6f58)) | ||
<a name="2.0.1"></a> | ||
@@ -7,0 +17,0 @@ ## [2.0.1](https://github.com/vesparny/brcast/compare/v2.0.0...v2.0.1) (2017-06-28) |
@@ -10,10 +10,21 @@ function createBroadcast (initialState) { | ||
_state = state; | ||
Object.keys(listeners).forEach(function (id) { return listeners[id](_state); }); | ||
var keys = Object.keys(listeners); | ||
for (var i = 0; i < keys.length; i += 1) { | ||
// if a listener gets unsubscribed during setState we just skip it | ||
if (typeof listeners[keys[i]] !== 'undefined') { | ||
listeners[keys[i]](state); | ||
} | ||
} | ||
}; | ||
var subscribe = function (listener) { | ||
if (typeof listener !== 'function') { throw new Error('listener must be a function.') } | ||
var currentId = id; | ||
var isSubscribed = true; | ||
listeners[currentId] = listener; | ||
id += 1; | ||
return function unsubscribe () { | ||
// in case unsubscribe gets called multiple times we simply return | ||
if (!isSubscribed) { return } | ||
isSubscribed = false; | ||
delete listeners[currentId]; | ||
@@ -20,0 +31,0 @@ } |
@@ -1,2 +0,2 @@ | ||
function createBroadcast(t){var e={},r=0,n=t;return{getState:function(){return n},setState:function(t){n=t,Object.keys(e).forEach(function(t){return e[t](n)})},subscribe:function(t){var n=r;return e[n]=t,r+=1,function(){delete e[n]}}}}module.exports=createBroadcast; | ||
function createBroadcast(t){var e={},r=0,n=t;return{getState:function(){return n},setState:function(t){n=t;for(var r=Object.keys(e),o=0;o<r.length;o+=1)void 0!==e[r[o]]&&e[r[o]](t)},subscribe:function(t){if("function"!=typeof t)throw new Error("listener must be a function.");var n=r,o=!0;return e[n]=t,r+=1,function(){o&&(o=!1,delete e[n])}}}}module.exports=createBroadcast; | ||
//# sourceMappingURL=brcast.cjs.min.js.map |
@@ -10,10 +10,21 @@ function createBroadcast (initialState) { | ||
_state = state; | ||
Object.keys(listeners).forEach(function (id) { return listeners[id](_state); }); | ||
var keys = Object.keys(listeners); | ||
for (var i = 0; i < keys.length; i += 1) { | ||
// if a listener gets unsubscribed during setState we just skip it | ||
if (typeof listeners[keys[i]] !== 'undefined') { | ||
listeners[keys[i]](state); | ||
} | ||
} | ||
}; | ||
var subscribe = function (listener) { | ||
if (typeof listener !== 'function') { throw new Error('listener must be a function.') } | ||
var currentId = id; | ||
var isSubscribed = true; | ||
listeners[currentId] = listener; | ||
id += 1; | ||
return function unsubscribe () { | ||
// in case unsubscribe gets called multiple times we simply return | ||
if (!isSubscribed) { return } | ||
isSubscribed = false; | ||
delete listeners[currentId]; | ||
@@ -20,0 +31,0 @@ } |
@@ -16,10 +16,21 @@ (function (global, factory) { | ||
_state = state; | ||
Object.keys(listeners).forEach(function (id) { return listeners[id](_state); }); | ||
var keys = Object.keys(listeners); | ||
for (var i = 0; i < keys.length; i += 1) { | ||
// if a listener gets unsubscribed during setState we just skip it | ||
if (typeof listeners[keys[i]] !== 'undefined') { | ||
listeners[keys[i]](state); | ||
} | ||
} | ||
}; | ||
var subscribe = function (listener) { | ||
if (typeof listener !== 'function') { throw new Error('listener must be a function.') } | ||
var currentId = id; | ||
var isSubscribed = true; | ||
listeners[currentId] = listener; | ||
id += 1; | ||
return function unsubscribe () { | ||
// in case unsubscribe gets called multiple times we simply return | ||
if (!isSubscribed) { return } | ||
isSubscribed = false; | ||
delete listeners[currentId]; | ||
@@ -26,0 +37,0 @@ } |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.brcast=t()}(this,function(){function e(e){var t={},n=0,o=e;return{getState:function(){return o},setState:function(e){o=e,Object.keys(t).forEach(function(e){return t[e](o)})},subscribe:function(e){var o=n;return t[o]=e,n+=1,function(){delete t[o]}}}}return e}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.brcast=t()}(this,function(){function e(e){var t={},n=0,o=e;return{getState:function(){return o},setState:function(e){o=e;for(var n=Object.keys(t),r=0;r<n.length;r+=1)void 0!==t[n[r]]&&t[n[r]](e)},subscribe:function(e){if("function"!=typeof e)throw new Error("listener must be a function.");var o=n,r=!0;return t[o]=e,n+=1,function(){r&&(r=!1,delete t[o])}}}}return e}); | ||
//# sourceMappingURL=brcast.umd.min.js.map |
13
index.js
@@ -10,10 +10,21 @@ export default function createBroadcast (initialState) { | ||
_state = state | ||
Object.keys(listeners).forEach(id => listeners[id](_state)) | ||
const keys = Object.keys(listeners) | ||
for (let i = 0; i < keys.length; i += 1) { | ||
// if a listener gets unsubscribed during setState we just skip it | ||
if (typeof listeners[keys[i]] !== 'undefined') { | ||
listeners[keys[i]](state) | ||
} | ||
} | ||
} | ||
const subscribe = listener => { | ||
if (typeof listener !== 'function') { throw new Error('listener must be a function.') } | ||
const currentId = id | ||
let isSubscribed = true | ||
listeners[currentId] = listener | ||
id += 1 | ||
return function unsubscribe () { | ||
// in case unsubscribe gets called multiple times we simply return | ||
if (!isSubscribed) return | ||
isSubscribed = false | ||
delete listeners[currentId] | ||
@@ -20,0 +31,0 @@ } |
@@ -1,50 +0,108 @@ | ||
import test from 'tape' | ||
import sinon from 'sinon' | ||
import brcast from './index' | ||
test('default export is a function', t => { | ||
t.ok(typeof brcast === 'function') | ||
t.end() | ||
test('default export is a function', () => { | ||
expect(typeof brcast).toBe('function') | ||
}) | ||
test('brcast().getState()', t => { | ||
test('throws if listener is not a function', () => { | ||
const broadcast = brcast() | ||
t.equal(broadcast.getState(), undefined, 'works without initial state') | ||
expect(() => broadcast.subscribe()).toThrow() | ||
expect(() => broadcast.subscribe('throw')).toThrow() | ||
expect(() => broadcast.subscribe({})).toThrow() | ||
expect(() => broadcast.subscribe(() => {})).not.toThrow() | ||
}) | ||
test('is able to start with an undefined state and update it accordingly', () => { | ||
const broadcast = brcast() | ||
expect(broadcast.getState()).toBeUndefined() | ||
broadcast.setState(2) | ||
t.equal(broadcast.getState(), 2, 'updates states accordingly') | ||
t.end() | ||
expect(broadcast.getState()).toBe(2) | ||
}) | ||
test('brcast().setState()', t => { | ||
const handler = sinon.spy() | ||
test('it updates the state', () => { | ||
const handler = jest.fn() | ||
const broadcast = brcast() | ||
broadcast.subscribe(handler) | ||
broadcast.setState(2) | ||
t.ok( | ||
handler.callCount === 1 && handler.calledWith(2), | ||
'the event handler is invoked with the state value as a parameter' | ||
) | ||
t.end() | ||
expect(handler.mock.calls.length).toBe(1) | ||
expect(handler.mock.calls[0][0]).toBe(2) | ||
}) | ||
test('brcast().subscribe()', t => { | ||
const handler = sinon.spy() | ||
const handler1 = sinon.spy() | ||
test('it unsubscribes only relevant listeners', () => { | ||
const handler = jest.fn() | ||
const handler1 = jest.fn() | ||
const broadcast = brcast(1) | ||
const subscription = broadcast.subscribe(handler) | ||
const subscription1 = broadcast.subscribe(handler1) | ||
t.ok( | ||
typeof subscription === 'function', | ||
'broadcast.subscribe(handler) returns a function' | ||
) | ||
broadcast.subscribe(handler1) | ||
expect(typeof subscription).toBe('function') | ||
subscription() | ||
broadcast.setState(2) | ||
broadcast.setState(3) | ||
t.ok( | ||
handler.callCount === 0, | ||
'when the unsubscribe function is invoked, the handler is not invoked anymore' | ||
expect(handler.mock.calls.length).toBe(0) | ||
expect(handler1.mock.calls.length).toBe(2) | ||
}) | ||
test('removes listeners only once when unsubscribing more than once', () => { | ||
const handler = jest.fn() | ||
const broadcast = brcast(1) | ||
const subscription = broadcast.subscribe(handler) | ||
subscription() | ||
subscription() | ||
broadcast.setState(2) | ||
expect(handler.mock.calls.length).toBe(0) | ||
}) | ||
test('supports removing a subscription within a subscription', () => { | ||
const broadcast = brcast(1) | ||
const handler = jest.fn() | ||
const handler1 = jest.fn() | ||
const handler2 = jest.fn() | ||
broadcast.subscribe(handler) | ||
const unSub1 = broadcast.subscribe(() => { | ||
handler1() | ||
unSub1() | ||
}) | ||
broadcast.subscribe(handler2) | ||
broadcast.setState(2) | ||
broadcast.setState(3) | ||
expect(handler.mock.calls.length).toBe(2) | ||
expect(handler1.mock.calls.length).toBe(1) | ||
expect(handler2.mock.calls.length).toBe(2) | ||
}) | ||
test('do not notify subscribers getting unsubscribed in the middle of a setState', () => { | ||
const broadcast = brcast() | ||
const unsubscribeHandles = [] | ||
const doUnsubscribeAll = () => | ||
unsubscribeHandles.forEach(unsubscribe => unsubscribe()) | ||
const handler = jest.fn() | ||
const handler1 = jest.fn() | ||
const handler2 = jest.fn() | ||
unsubscribeHandles.push(broadcast.subscribe(handler)) | ||
unsubscribeHandles.push( | ||
broadcast.subscribe(() => { | ||
handler1() | ||
doUnsubscribeAll() | ||
}) | ||
) | ||
t.ok(handler1.callCount === 2, 'other handlers still get invoked') | ||
subscription1() | ||
t.end() | ||
unsubscribeHandles.push(broadcast.subscribe(handler2)) | ||
broadcast.setState(2) | ||
expect(handler.mock.calls.length).toBe(1) | ||
expect(handler1.mock.calls.length).toBe(1) | ||
expect(handler2.mock.calls.length).toBe(0) | ||
broadcast.setState(3) | ||
expect(handler.mock.calls.length).toBe(1) | ||
expect(handler1.mock.calls.length).toBe(1) | ||
expect(handler2.mock.calls.length).toBe(0) | ||
}) |
{ | ||
"name": "brcast", | ||
"amdName": "brcast", | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"description": "Tiny data broadcaster with 0 dependencies", | ||
@@ -12,3 +12,3 @@ "jsnext:main": "index.js", | ||
"bump": "standard-version", | ||
"testonly": "tape -r babel-register *.spec.js | tap-spec", | ||
"testonly": "jest --coverage", | ||
"lint": "standard", | ||
@@ -22,2 +22,3 @@ "format": "prettier --write --semi false '*.js' && standard --fix", | ||
"size": "echo \"Gzipped Size: $(cat dist/brcast.umd.min.js | gzip-size)\"", | ||
"precommit": "lint-staged", | ||
"release": "npm run build && npm run bump && git push --follow-tags origin master && npm publish" | ||
@@ -49,4 +50,7 @@ }, | ||
"gzip-size-cli": "^2.0.0", | ||
"husky": "^0.14.3", | ||
"jest": "^20.0.4", | ||
"lint-staged": "^4.0.2", | ||
"npm-run-all": "^4.0.2", | ||
"prettier": "^1.1.0", | ||
"prettier": "^1.5.3", | ||
"rimraf": "^2.5.2", | ||
@@ -56,9 +60,23 @@ "rollup": "^0.41.4", | ||
"rollup-plugin-uglify": "^1.0.1", | ||
"sinon": "^2.1.0", | ||
"standard": "^10.0.2", | ||
"standard-version": "^4.0.0", | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.6.3" | ||
"standard-version": "^4.0.0" | ||
}, | ||
"dependencies": {} | ||
"dependencies": {}, | ||
"standard": { | ||
"parser": "babel-eslint", | ||
"globals": [ | ||
"jest", | ||
"expect", | ||
"it", | ||
"test", | ||
"describe" | ||
] | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"prettier --write --semi false --single-quote", | ||
"standard --fix", | ||
"git add" | ||
] | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
19049
13
224
0
82