-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
140 lines (115 loc) · 3.1 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
/**
* @copyright Maichong Software Ltd. 2016 http://maichong.it
* @date 2016-01-19
* @author Liang <[email protected]>
*/
'use strict';
/**
* @param obj
* @param method
* @param original
*/
function collie(obj, method, original) {
//记录原始函数
original = original || obj[method];
//存放hooks函数
obj._hooks = obj._hooks || {};
obj._hooks[method] = obj._hooks[method] || { pre: [], post: [] };
obj.pre = function pre(name, fn) {
if (!obj._hooks[name]) {
throw new Error('collie: can not hook method "' + name + '"');
}
obj._hooks[name].pre.push(fn);
};
obj.post = function post(name, fn) {
if (!obj._hooks[name]) {
throw new Error('collie: can not hook method "' + name + '"');
}
obj._hooks[name].post.push(fn);
};
//大写字母开头的方法名称
var Method = method.replace(/^\w/, function (match) {
return match.toUpperCase();
});
var preMethod = 'pre' + Method;
var postMethod = 'post' + Method;
//覆盖原有方法
obj[method] = function () {
var args = arguments;
var results = [null].concat(Array.prototype.slice.call(args));
let preHooks = [];
//异步执行pre hooks
obj._hooks[method].pre.forEach(function (fn) {
preHooks.push(fn);
});
if (obj[preMethod]) {
//异步执行对象preMethod方法
preHooks.push(obj[preMethod]);
}
//异步执行原始方法
preHooks.push(original);
var promise = compose(preHooks, args, obj);
//记录下方法的返回值
promise = promise.then(function (result) {
results[0] = result;
});
let postHooks = [];
if (obj[postMethod]) {
//异步执行对象postMethod方法
postHooks.push(obj[postMethod]);
}
//异步执行post hooks
obj._hooks[method].post.forEach(function (fn) {
postHooks.push(fn);
});
if (postHooks.length) {
promise = promise.then(function () {
return compose(postHooks, results, obj);
});
}
return promise.then(function () {
//异步返回原始函数返回值
return results[0];
});
};
}
/**
* 将多个hook函数合并为一个异步函数
* @param hooks
* @param args
* @param scope
* @returns {Promise}
*/
function compose(hooks, args, scope) {
if (!Array.isArray(hooks)) throw new TypeError('Hooks stack must be an array!');
var promise = Promise.resolve();
var temp = {
args: args
};
hooks.forEach(function (fn) {
if (typeof fn !== 'function') throw new TypeError('Hooks must be composed of functions!');
promise = promise.then(function () {
return new Promise(function (resolve, reject) {
function callback(res) {
if (Array.isArray(res)) {
temp.args = res;
}
resolve(res);
}
try {
var res = fn.apply(scope, temp.args);
if (res && res.then) {
res.then(callback, reject);
} else {
callback(res);
}
} catch (error) {
reject(error);
}
});
});
});
return promise;
}
collie.compose = compose;
module.exports = collie;