This repository has been archived by the owner on Oct 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathindex.js
executable file
·153 lines (134 loc) · 3.48 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import curry from 'lodash/fp/curry'
import curryN from 'lodash/fp/curryN'
import attempt from 'lodash/fp/attempt'
import isError from 'lodash/fp/isError'
import isFunction from 'lodash/fp/isFunction'
import isArray from 'lodash/fp/isArray'
import _once from 'lodash/fp/once'
import propSet from 'lodash/fp/set'
import reduce from 'lodash/fp/reduce'
import memoize from 'lodash/fp/memoize'
import mapValues from 'lodash/fp/mapValues'
function isThenable (f) {
return f && isFunction(f.then)
}
// eval trackFn before fn
export const before = curryN(2, (trackFn, fn) => function (...args) {
try {
isFunction(trackFn) && trackFn.apply(this, args)
} catch(e) {
console.error(e)
}
return fn.apply(this, args)
})
// eval trackFn after fn
export const after = curryN(2, (trackFn, fn) => function (...args) {
const r = fn.apply(this, args)
const self = this
const evalF = () => {
try {
trackFn.apply(self, args)
} catch (e) {
console.error(e)
}
}
if (isThenable(r)) {
return r.then(rr => {
evalF()
return rr
})
}
evalF()
return r
})
// track by decorator
/* class SomeComponent {
* @track(before(() => console.log('hello, trackpoint')))
* onClick = () => {
* ...
* }
* }*/
export const track = partical => (target, key, descriptor) => {
if (!isFunction (partical)) {
throw new Error('trackFn is not a function ' + partical)
}
const value = function (...args) {
return partical.call(this, descriptor.value, this).apply(this, args)
}
if (descriptor.initializer) {
return propSet('initializer', function() {
const value = descriptor.initializer.apply(this);
return function (...args) {
return partical.call(this, value, this).apply(this, args);
}
}, descriptor);
}
return propSet('value', value, descriptor)
}
// composeWith convergeFn by ops[array]
export const composeWith = curry((convergeFn, ops) => {
if (isFunction (ops)) {
ops = [ops]
}
// type check
if (!isFunction(convergeFn) ||!isArray(ops) ) {
return console.error('args type incorrect, expect convergeFn is function and ops is array')
}
const compose = reduce((acc, i) => {
if (!acc) {
return acc || i
}
return i.call(null, acc)
}, null)
return curryN(1, (fn, target) => function (...args) {
const memoizeFn = memoize(fn)
const _r = convergeFn(
compose(ops)
.apply(this, [memoizeFn])
.apply(this, args)
).apply(this, args)
return memoizeFn.apply(this, args)
})
})
export const createCounter = () => {
let scopeCounter = 0
return fn => function (...args) {
fn.apply(this, args)
scopeCounter = scopeCounter + 1
return scopeCounter
}
}
export const time = fn => function (...args) {
const begin = +Date.now()
const result = fn.apply(this, args)
// result will be cached by memoize, so return new promise
if (isThenable(result)) {
return result.then(() => +Date.now() - begin)
}
return +Date.now() - begin
}
export const evolve = curry(evols => fn => function (...args) {
const self = this
const memoizeFn = memoize(fn)
return mapValues((value) => {
return value(memoizeFn).apply(self, args)
}, evols)
})
export const identity = curry(fn => function (...args) {
return fn.apply(this, args)
})
// do work nothing
export const nop = () => {}
export const once = _once
export default {
before,
after,
track,
nop,
once,
composeWith,
time,
evolve,
identity,
createCounter
}