Advertisement
Guest User

Untitled

a guest
Oct 10th, 2015
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.28 KB | None | 0 0
  1. 'use strict'
  2.  
  3. import {
  4. EventEmitter
  5. } from 'events'
  6.  
  7.  
  8. const keyRegExp = /\{(\w+)\}/g
  9. const sep = '.'
  10.  
  11. function resolveParam(keyPath, payload){
  12. return keyPath
  13. .replace(
  14. keyRegExp
  15. , (_,$1) => payload[$1]
  16. )
  17. .split(sep)
  18. }
  19. function walk(cur, tiers, lvl = 0){
  20. if(tiers.length === 0){
  21. return cur
  22. }
  23. let prop = cur[tiers[0]]
  24. let tails = tiers.slice(1)
  25. if(tails.length === 0){
  26. return prop
  27. }else if(prop === undefined || prop === null){
  28. throw new Error(` {lvl} `)
  29. }else{
  30. return walk(prop, tails, lvl + 1)
  31. }
  32. }
  33.  
  34. const evName = 'change'
  35.  
  36. function deepMerge(tiers, source, patch){
  37. //FIXME Immutable!
  38. let target = source
  39. let locationTiers = tiers.slice(0,tiers.length - 1)
  40. let patchKey = tiers[tiers.length - 1]
  41. walk(target, locationTiers)[patchKey] = patch
  42. return target
  43. }
  44.  
  45. export default function Effector(initialState = {}){
  46. let currentState = initialState
  47. let broadcastMap = {}
  48. const emitter = new EventEmitter()
  49. const getState = () => currentState
  50. const subscribe = (fn) => {
  51. let cb = (nextState) => fn(nextState)
  52. emitter.addListener(evName, cb)
  53. return () => emitter.removeListener(evName, cb)
  54. }
  55. const createAction = (keyPath, fn, deps = []) => {
  56. let action = (payload, options = {}) => {
  57.  
  58. let tiers = resolveParam(keyPath, payload)
  59. let source = walk(currentState, tiers)
  60. let args = [payload, source].concat(deps.map((dp) => {
  61. return walk(currentState, resolveParam(dp, payload))
  62. }))
  63. args.push(function resolve(target){
  64.  
  65. currentState = deepMerge(tiers, currentState, target)
  66. Object.keys(broadcastMap).forEach((path) => {
  67. if(keyPath.indexOf(path) > 0){
  68. broadcastMap[path].forEach((subcriber) => {
  69. subcriber(payload, {trigger:false})
  70. })
  71. }
  72. })
  73. if(options.trigger !== false){
  74. emitter.emit(evName, currentState)
  75. }
  76. })
  77. return fn.apply(null, args)
  78. }
  79. action.listenTo = (path) => {
  80. var subcribers;
  81. if(!broadcastMap[path]){
  82. subcribers = broadcastMap[path] = [action]
  83. }else{
  84. subcribers = broadcastMap[path]
  85. }
  86. return action
  87. }
  88.  
  89. return action
  90. }
  91. return {
  92. createAction,
  93. subscribe,
  94. getState
  95. }
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement