Skip to content

Commit 30d037d

Browse files
committed
feat(redux): dispatcher with middleware (#97)
* chore(npm): update no-mix-dearu-desumasu@3 * feat(redux): add dispatcher with middleware * test(redux): add logger middleware test
1 parent b5f4779 commit 30d037d

File tree

7 files changed

+117
-3
lines changed

7 files changed

+117
-3
lines changed

.textlintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"no-mix-dearu-desumasu": {
2222
"preferInHeader": "",
2323
"preferInBody": "ですます",
24-
"preferInList": "である"
24+
"preferInList": "である",
25+
"strict": true
2526
},
2627
"prh": {
2728
"rulePaths": [

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ Pull Request、コミットのやりかたなどが書かれています。
6060

6161
コードはMITライセンスで利用できます。
6262
文章は[CC BY-NC 4.0](http://creativecommons.org/licenses/by-nc/4.0/ "CC BY-NC 4.0")で利用できます。
63+

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"textlint-rule-no-doubled-conjunctive-particle-ga": "^1.0.2",
7272
"textlint-rule-no-doubled-joshi": "^3.2.0",
7373
"textlint-rule-no-dropping-the-ra": "^1.0.2",
74-
"textlint-rule-no-mix-dearu-desumasu": "^2.2.1",
74+
"textlint-rule-no-mix-dearu-desumasu": "^3.0.0",
7575
"textlint-rule-no-nfd": "^1.0.1",
7676
"textlint-rule-no-start-duplicated-conjunction": "^1.0.7",
7777
"textlint-rule-preset-jtf-style": "^2.0.0",

src/redux/Dispatcher.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// LICENSE : MIT
2+
"use strict";
3+
const assert = require("assert");
4+
const EventEmitter = require("events");
5+
export const ON_DISPATCH = "__ON_DISPATCH__";
6+
/**
7+
* payload The payload object that must have `type` property.
8+
* @typedef {Object} DispatcherPayload
9+
* @property {String} type The event type to dispatch.
10+
* @public
11+
*/
12+
export default class Dispatcher extends EventEmitter {
13+
/**
14+
* add onAction handler and return unbind function
15+
* @param {function(DispatcherPayload)} payloadHandler
16+
* @returns {Function} call the function and release handler
17+
* @public
18+
*/
19+
onDispatch(payloadHandler) {
20+
this.on(ON_DISPATCH, payloadHandler);
21+
return this.removeListener.bind(this, ON_DISPATCH, payloadHandler);
22+
}
23+
24+
/**
25+
* dispatch action object.
26+
* StoreGroups receive this action and reduce state.
27+
* @param {DispatcherPayload} payload
28+
* @public
29+
*/
30+
dispatch(payload) {
31+
assert(payload !== undefined && payload !== null, "payload should not null or undefined");
32+
assert(typeof payload.type === "string", "payload's type should be string");
33+
this.emit(ON_DISPATCH, payload);
34+
}
35+
36+
}

src/redux/apply-middleware.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// LICENSE : MIT
2+
"use strict";
3+
// core -
4+
// next - next function
5+
// action - action object
6+
const applyMiddlewares = (...middlewares) => {
7+
return middlewareAPI => {
8+
const originalDispatch = middlewareAPI.dispatch.bind(middlewareAPI);
9+
const wrapMiddleware = middlewares.map(middleware => {
10+
return middleware(middlewareAPI);
11+
});
12+
// apply middleware order by first
13+
const last = wrapMiddleware[wrapMiddleware.length - 1];
14+
const rest = wrapMiddleware.slice(0, -1);
15+
const roundDispatch = rest.reduceRight((oneMiddle, middleware) => {
16+
return middleware(oneMiddle);
17+
}, last);
18+
return roundDispatch(originalDispatch);
19+
};
20+
};
21+
22+
export default applyMiddlewares;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// LICENSE : MIT
2+
"use strict";
3+
const assert = require("power-assert");
4+
import applyMiddleware from "../../src/redux/apply-middleware";
5+
import Dispatcher from "../../src/redux/Dispatcher";
6+
import timestamp from "../../src/redux/timestamp";
7+
import createLogger from "../../src/redux/logger";
8+
describe("middleware", function () {
9+
it("could apply logger middleware", function () {
10+
const dispatcher = new Dispatcher();
11+
const logs = [];
12+
const con = {
13+
log(message){
14+
logs.push(message);
15+
}
16+
};
17+
const middleware = createLogger({
18+
logger: con
19+
});
20+
// state
21+
const state = {};
22+
const middlewareAPI = {
23+
getState(){
24+
return state;
25+
},
26+
dispatch(action){
27+
dispatcher.dispatch(action);
28+
}
29+
};
30+
const dispatchWithMiddleware = applyMiddleware(middleware)(middlewareAPI);
31+
const action = {type: "FOO"};
32+
// then
33+
dispatcher.onDispatch(payload => {
34+
if(payload.type === "FOO"){
35+
state.isUpdated = true;
36+
}
37+
});
38+
// when
39+
dispatchWithMiddleware(action);
40+
assert.deepEqual(logs, [action, state]);
41+
});
42+
it("could apply timestamp middleware", function (done) {
43+
const dispatcher = new Dispatcher();
44+
const dispatchWithMiddleware = applyMiddleware(timestamp)(dispatcher);
45+
const action = {type: "FOO"};
46+
// then
47+
dispatcher.onDispatch(payload => {
48+
assert(typeof payload.timeStamp === "number");
49+
done();
50+
});
51+
// when
52+
dispatchWithMiddleware(action);
53+
});
54+
});

test/redux/timestamp-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const reducer = (state = initialState, action) => {
1313
}
1414
};
1515

16-
describe("logger-test", function () {
16+
describe("timestamp-test", function () {
1717
let store, dispatch;
1818
beforeEach(() => {
1919
store = applyMiddleware(timestamp)(createStore)(reducer);

0 commit comments

Comments
 (0)