Skip to content

Commit 6080fc1

Browse files
committed
1.0.1
1 parent d361ce5 commit 6080fc1

9 files changed

+412
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea

README.md

+88-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,88 @@
1-
# decorators-es6
1+
# decorators-es6
2+
Decorator for es6+, with promise support
3+
### Install
4+
```
5+
npm install decorators-es6
6+
```
7+
```
8+
yarn add decorators-es6
9+
```
10+
11+
### Decorators
12+
* debounce
13+
* memoize
14+
* cache - alias for memoize
15+
* throttle
16+
17+
### Features
18+
* Easy to use as decorator
19+
* Promise support
20+
* Decorated function return value in promise chain
21+
22+
### Usage
23+
#### debounce(time)
24+
Default debounce time = 500ms
25+
```javascript
26+
import { debounce } from 'decorators-es6';
27+
28+
class Store {
29+
message = 'msg';
30+
31+
@debounce(1000)
32+
changeMessage = (message) => {
33+
this.message = message;
34+
return 'updated';
35+
};
36+
37+
@debounce(1000)
38+
updateOnServer = (message) => {
39+
return axios.post('/message/update', {message});
40+
}
41+
}
42+
43+
const store = new Store();
44+
store.changeMessage('msg2');
45+
46+
store.changeMessage('msg2').then(value => {
47+
//debounce firing;
48+
console.log(value) // 'updated'
49+
});
50+
51+
store.updateOnServer('msg2').then(response => {
52+
//debounce firing;
53+
console.log(response) // axios response from server(Promise resolve)
54+
});
55+
```
56+
57+
#### memoize(time) or cache(time)
58+
Default memoize time = 9999999ms
59+
```javascript
60+
import { memoize} from 'decorators-es6';
61+
62+
class Service {
63+
@memoize()
64+
calc = (number) => {
65+
return number * 5;
66+
};
67+
68+
// memoize product info for 100 secs
69+
@memoize(100000)
70+
getProductFromServer = (productId) => {
71+
return axios.post('/product', {productId});
72+
}
73+
}
74+
75+
const service = new Service();
76+
service.calc(10).then(result => {
77+
console.log(result);
78+
})
79+
80+
service.getProductFromServer().then(response => {
81+
console.log(response); // response from axios for example
82+
store.product = response.data.product;
83+
})
84+
```
85+
86+
#### throtle(time)
87+
Default debounce time = 500ms
88+
Example: see debounce example

index.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export cache from './src/cache';
2+
export debounce from './src/debounce';
3+
export memoize from './src/memoize';
4+
export throttle from './src/throttle';

package.json

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "decorators-es6",
3+
"version": "1.0.1",
4+
"description": "Useful decorators for es6+, with promise support",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/izica/decorators-es6.git"
12+
},
13+
"author": "Artyom Golovarchuk",
14+
"license": "MIT",
15+
"bugs": {
16+
"url": "https://github.com/izica/decorators-es6/issues"
17+
},
18+
"homepage": "https://github.com/izica/decorators-es6#readme",
19+
"keywords": [
20+
"es6",
21+
"javascript",
22+
"decorator",
23+
"promise",
24+
"promise-support",
25+
"decorator-es6",
26+
"javascript-es6",
27+
"debounce",
28+
"debounce-es6",
29+
"memoize",
30+
"memoize-es6",
31+
"throttle",
32+
"throttle-es6"
33+
]
34+
}

src/cache.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import cache from './memoize';
2+
3+
export default cache;

src/debounce.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const debounce = (time = 500) => {
2+
return (target, name, descriptor) => {
3+
return {
4+
configurable: true,
5+
enumerable: true,
6+
writable: true,
7+
initializer: () => function (...args) {
8+
return new Promise((resolve) => {
9+
if (typeof this.timeout !== 'undefined') {
10+
clearTimeout(this.timeout);
11+
}
12+
this.timeout = setTimeout(() => {
13+
const promiseOrResult = descriptor.initializer().apply(this, args);
14+
if (typeof promiseOrResult.then === 'undefined') {
15+
resolve(promiseOrResult);
16+
} else {
17+
promiseOrResult.then(result => {
18+
resolve(result);
19+
});
20+
}
21+
}, time);
22+
});
23+
}
24+
};
25+
};
26+
};
27+
28+
export default debounce;

src/lib/md5.js

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
(function(){
2+
var crypt = require('crypt'),
3+
utf8 = require('charenc').utf8,
4+
isBuffer = require('is-buffer'),
5+
bin = require('charenc').bin,
6+
7+
// The core
8+
md5 = function (message, options) {
9+
// Convert to byte array
10+
if (message.constructor == String)
11+
if (options && options.encoding === 'binary')
12+
message = bin.stringToBytes(message);
13+
else
14+
message = utf8.stringToBytes(message);
15+
else if (isBuffer(message))
16+
message = Array.prototype.slice.call(message, 0);
17+
else if (!Array.isArray(message) && message.constructor !== Uint8Array)
18+
message = message.toString();
19+
// else, assume byte array already
20+
21+
var m = crypt.bytesToWords(message),
22+
l = message.length * 8,
23+
a = 1732584193,
24+
b = -271733879,
25+
c = -1732584194,
26+
d = 271733878;
27+
28+
// Swap endian
29+
for (var i = 0; i < m.length; i++) {
30+
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
31+
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
32+
}
33+
34+
// Padding
35+
m[l >>> 5] |= 0x80 << (l % 32);
36+
m[(((l + 64) >>> 9) << 4) + 14] = l;
37+
38+
// Method shortcuts
39+
var FF = md5._ff,
40+
GG = md5._gg,
41+
HH = md5._hh,
42+
II = md5._ii;
43+
44+
for (var i = 0; i < m.length; i += 16) {
45+
46+
var aa = a,
47+
bb = b,
48+
cc = c,
49+
dd = d;
50+
51+
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
52+
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
53+
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
54+
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
55+
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
56+
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
57+
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
58+
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
59+
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
60+
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
61+
c = FF(c, d, a, b, m[i+10], 17, -42063);
62+
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
63+
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
64+
d = FF(d, a, b, c, m[i+13], 12, -40341101);
65+
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
66+
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
67+
68+
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
69+
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
70+
c = GG(c, d, a, b, m[i+11], 14, 643717713);
71+
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
72+
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
73+
d = GG(d, a, b, c, m[i+10], 9, 38016083);
74+
c = GG(c, d, a, b, m[i+15], 14, -660478335);
75+
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
76+
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
77+
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
78+
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
79+
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
80+
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
81+
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
82+
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
83+
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
84+
85+
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
86+
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
87+
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
88+
b = HH(b, c, d, a, m[i+14], 23, -35309556);
89+
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
90+
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
91+
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
92+
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
93+
a = HH(a, b, c, d, m[i+13], 4, 681279174);
94+
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
95+
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
96+
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
97+
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
98+
d = HH(d, a, b, c, m[i+12], 11, -421815835);
99+
c = HH(c, d, a, b, m[i+15], 16, 530742520);
100+
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
101+
102+
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
103+
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
104+
c = II(c, d, a, b, m[i+14], 15, -1416354905);
105+
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
106+
a = II(a, b, c, d, m[i+12], 6, 1700485571);
107+
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
108+
c = II(c, d, a, b, m[i+10], 15, -1051523);
109+
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
110+
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
111+
d = II(d, a, b, c, m[i+15], 10, -30611744);
112+
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
113+
b = II(b, c, d, a, m[i+13], 21, 1309151649);
114+
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
115+
d = II(d, a, b, c, m[i+11], 10, -1120210379);
116+
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
117+
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
118+
119+
a = (a + aa) >>> 0;
120+
b = (b + bb) >>> 0;
121+
c = (c + cc) >>> 0;
122+
d = (d + dd) >>> 0;
123+
}
124+
125+
return crypt.endian([a, b, c, d]);
126+
};
127+
128+
// Auxiliary functions
129+
md5._ff = function (a, b, c, d, x, s, t) {
130+
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
131+
return ((n << s) | (n >>> (32 - s))) + b;
132+
};
133+
md5._gg = function (a, b, c, d, x, s, t) {
134+
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
135+
return ((n << s) | (n >>> (32 - s))) + b;
136+
};
137+
md5._hh = function (a, b, c, d, x, s, t) {
138+
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
139+
return ((n << s) | (n >>> (32 - s))) + b;
140+
};
141+
md5._ii = function (a, b, c, d, x, s, t) {
142+
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
143+
return ((n << s) | (n >>> (32 - s))) + b;
144+
};
145+
146+
// Package private blocksize
147+
md5._blocksize = 16;
148+
md5._digestsize = 16;
149+
150+
module.exports = function (message, options) {
151+
if (message === undefined || message === null)
152+
throw new Error('Illegal argument ' + message);
153+
154+
var digestbytes = crypt.wordsToBytes(md5(message, options));
155+
return options && options.asBytes ? digestbytes :
156+
options && options.asString ? bin.bytesToString(digestbytes) :
157+
crypt.bytesToHex(digestbytes);
158+
};
159+
160+
})();

src/memoize.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import md5 from './lib/md5';
2+
3+
const getKey = (args) => {
4+
const json = JSON.stringify(args);
5+
return md5(json) + json.substr(0, 5) + json.substr(-5);
6+
};
7+
8+
const memoize = (time = 9999999) => {
9+
return (target, name, descriptor) => {
10+
return {
11+
configurable: true,
12+
enumerable: true,
13+
writable: true,
14+
initializer: () => function (...args) {
15+
return new Promise((resolve) => {
16+
if (typeof this.stash === 'undefined') {
17+
this.stash = {};
18+
}
19+
20+
const key = getKey(args);
21+
const dateCurrent = Date.now();
22+
23+
// get from stash
24+
if (typeof this.stash[key] !== 'undefined') {
25+
const resultFromStash = this.stash[key];
26+
if (resultFromStash.expires > dateCurrent) {
27+
resolve(resultFromStash.value);
28+
return;
29+
}
30+
}
31+
32+
// get new result
33+
const promiseOrResult = descriptor.initializer().apply(this, args);
34+
if (typeof promiseOrResult.then === 'undefined') {
35+
this.stash[key] = {
36+
expires: dateCurrent + time,
37+
value: promiseOrResult
38+
};
39+
resolve(promiseOrResult);
40+
} else {
41+
promiseOrResult.then(result => {
42+
this.stash[key] = {
43+
expires: dateCurrent + time,
44+
value: result
45+
};
46+
resolve(result);
47+
});
48+
}
49+
});
50+
}
51+
};
52+
};
53+
};
54+
55+
export default memoize;

0 commit comments

Comments
 (0)