forked from papertiger8848/modelproxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
modelproxy.js
162 lines (138 loc) · 4.96 KB
/
modelproxy.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
154
155
156
157
158
159
160
161
162
/**
* ModelProxy
* As named, this class is provided to model the proxy.
* @author ShanFan
* @created 24-3-2014
**/
// Dependencies
var InterfaceManager = require( './interfacemanager' )
, ProxyFactory = require( './proxyfactory' );
/**
* ModelProxy Constructor
* @param {Object|Array|String} profile. This profile describes what the model looks
* like. eg:
* profile = {
* getItems: 'Search.getItems',
* getCart: 'Cart.getCart'
* }
* profile = ['Search.getItems', 'Cart.getCart']
* profile = 'Search.getItems'
* profile = 'Search.*'
*/
function ModelProxy( profile ) {
if ( !profile ) return;
if ( typeof profile === 'string' ) {
// Get ids via prefix pattern like 'packageName.*'
if ( /^(\w+\.)+\*$/.test( profile ) ) {
profile = ProxyFactory
.getInterfaceIdsByPrefix( profile.replace( /\*$/, '' ) );
} else {
profile = [ profile ];
}
}
if ( profile instanceof Array ) {
var prof = {}, methodName;
for ( var i = profile.length - 1; i >= 0; i-- ) {
methodName = profile[ i ];
methodName = methodName
.substring( methodName.lastIndexOf( '.' ) + 1 );
if ( !prof[ methodName ] ) {
prof[ methodName ] = profile[ i ];
// The method name is duplicated, so the full interface id is set
// as the method name.
} else {
methodName = profile[ i ].replace( /\./g, '_' );
prof[ methodName ] = profile[ i ];
}
}
profile = prof;
}
// Construct the model following the profile
for ( var method in profile ) {
this[ method ] = ( function( methodName, interfaceId ) {
var proxy = ProxyFactory.create( interfaceId );
return function( params ) {
params = params || {};
if ( !this._queue ) {
this._queue = [];
}
// Push this method call into request queue. Once the done method
// is called, all requests in this queue will be sent.
this._queue.push( {
params: params,
proxy: proxy
} );
return this;
};
} )( method, profile[ method ] );
// this._addMethod( method, profile[ method ] );
}
}
ModelProxy.prototype = {
done: function( f, ef ) {
if ( typeof f !== 'function' ) return;
// No request pushed in _queue, so callback directly and return.
if ( !this._queue ) {
f.apply( this );
return;
}
// Send requests parallel
this._sendRequestsParallel( this._queue, f, ef );
// Clear queue
this._queue = null;
return this;
},
withCookie: function( cookie ) {
this._cookies = cookie;
return this;
},
_sendRequestsParallel: function( queue, callback, errCallback ) {
// The final data array
var args = [], setcookies = [], self = this;
// Count the number of callback;
var cnt = queue.length;
// Send each request
for ( var i = 0; i < queue.length; i++ ) {
( function( reqObj, k, cookie ) {
reqObj.proxy.request( reqObj.params, function( data, setcookie ) {
// fill data for callback
args[ k ] = data;
// concat setcookie for cookie rewriting
setcookies = setcookies.concat( setcookie );
args.push( setcookies );
// push the set-cookies as the last parameter for the callback function.
--cnt || callback.apply( self, args.push( setcookies ) && args );
}, function( err ) {
errCallback = errCallback || self._errCallback;
if ( typeof errCallback === 'function' ) {
errCallback( err );
} else {
console.error( 'Error occured when sending request ='
, reqObj.params, '\nCaused by:\n', err );
}
}, cookie ); // request with cookie.
} )( queue[i], i, self._cookies );
}
// clear cookie of this request.
self._cookies = undefined;
},
error: function( f ) {
this._errCallback = f;
}
};
/**
* ModelProxy.init
* @param {String} path The path refers to the interface configuration file.
*/
ModelProxy.init = function( path ) {
ProxyFactory.use( new InterfaceManager( path ) );
};
ModelProxy.create = function( profile ) {
return new this( profile );
};
ModelProxy.Interceptor = function( req, res ) {
// todo: need to handle the case that the request url is multiple
// interfaces combined which configured in interface.json.
ProxyFactory.Interceptor( req, res );
};
module.exports = ModelProxy;