1 | const version = '0.3.23';
|
2 |
|
3 |
|
4 | var index = ({
|
5 | r,
|
6 | l,
|
7 | mount,
|
8 | headless,
|
9 | Component,
|
10 | }, config = {}) => {
|
11 | let prefix = (config.baseUrl || '').replace(/\/$/, '');
|
12 | let dummy = config.dummy;
|
13 | let dummyData = config.dummyData || {};
|
14 |
|
15 | let fetchdummy = (type, key, cb) => {
|
16 | setTimeout(() => {
|
17 | cb(dummyData[type] && dummyData[type][key] || null);
|
18 | }, config.dummyTimeout || 100);
|
19 | };
|
20 |
|
21 | let HTTP = function HTTP(t, url, params, headers, loading) {
|
22 | this.localDummy = config.dummy;
|
23 | this.url = url;
|
24 | this.id = url + '';
|
25 | this.type = t;
|
26 | this.start = () => loading.start(this.id);
|
27 | this.end = () => loading.end(this.id);
|
28 | this.http = new XMLHttpRequest();
|
29 | this.headers = Object.assign(config.headers || {}, headers || {});
|
30 | this.params = JSON.stringify(params);
|
31 | this.resolve = () => {
|
32 | this.end();
|
33 | };
|
34 | this.reject = e => {
|
35 | console.error('[Radi Fetch] WARN: Request caught an error.\n', e);
|
36 | this.end();
|
37 | };
|
38 |
|
39 | let n = url.split('?').length - 1;
|
40 | if (t === 'get')
|
41 | for (let i in params) {
|
42 | url = url.concat(((!n)?'?':'&') + i + '=' + params[i]);
|
43 | n += 1;
|
44 | }
|
45 |
|
46 | this.http.open(t, prefix + url, true);
|
47 |
|
48 | for (let h in this.headers) {
|
49 | this.http.setRequestHeader(h, this.headers[h]);
|
50 | }
|
51 |
|
52 |
|
53 | this.abort = (...args) => this.http.abort(...args);
|
54 | this.tag = key => (this.id = key, this);
|
55 | };
|
56 |
|
57 | HTTP.prototype.dummy = function (status = true) {
|
58 | this.localDummy = status;
|
59 | return this
|
60 | };
|
61 |
|
62 | HTTP.prototype.catch = function (ERR) {
|
63 | if (typeof ERR === 'function') {
|
64 | this.reject = (...args) => {
|
65 | ERR(...args);
|
66 | this.end();
|
67 | };
|
68 | }
|
69 | return this
|
70 | };
|
71 |
|
72 | HTTP.prototype.then = function then(OK, ERR) {
|
73 | this.start();
|
74 | if (typeof OK === 'function') {
|
75 | this.resolve = (...args) => {
|
76 | OK(...args);
|
77 | this.end();
|
78 | };
|
79 | }
|
80 | if (typeof ERR === 'function') {
|
81 | this.reject = (...args) => {
|
82 | ERR(...args);
|
83 | this.end();
|
84 | };
|
85 | }
|
86 | if (this.localDummy || dummy) {
|
87 | fetchdummy(this.type, this.url, data => {
|
88 | this.resolve({
|
89 | headers: '',
|
90 | status: 'dummy',
|
91 | response: JSON.stringify(data),
|
92 | text: () => JSON.stringify(data),
|
93 | json: () => data,
|
94 | });
|
95 | });
|
96 | return this;
|
97 | }
|
98 | let self = this;
|
99 | this.http.onreadystatechange = function(e) {
|
100 | let res = this;
|
101 | if (res.readyState === XMLHttpRequest.DONE) {
|
102 | let h = {
|
103 | headers: self.http.getAllResponseHeaders(),
|
104 | status: res.status,
|
105 | response: res.response
|
106 | };
|
107 | if (res.status === 200) {
|
108 | h.text = function() { return res.responseText };
|
109 | h.json = function() {
|
110 | try {
|
111 | return JSON.parse(this.text());
|
112 | }
|
113 | catch(error) {
|
114 | console.error('[Radi Fetch] WARN: Response is not JSON, using fallback to empty JSON.\n', error);
|
115 | return {};
|
116 | }
|
117 | };
|
118 | self.resolve(h);
|
119 | } else {
|
120 | self.reject(h);
|
121 | }
|
122 | }
|
123 | };
|
124 | this.http.send(this.params);
|
125 | return this
|
126 | };
|
127 |
|
128 | class Fetch extends Component {
|
129 | get(u, p, h) { return new HTTP('get', u, p, h, this.$loading) }
|
130 | post(u, p, h) { return new HTTP('post', u, p, h, this.$loading) }
|
131 | put(u, p, h) { return new HTTP('put', u, p, h, this.$loading) }
|
132 | delete(u, p, h) { return new HTTP('delete', u, p, h, this.$loading) }
|
133 | options(u, p, h) { return new HTTP('options', u, p, h, this.$loading) }
|
134 | head(u, p, h) { return new HTTP('head', u, p, h, this.$loading) }
|
135 | }
|
136 |
|
137 | class Loading extends Component {
|
138 | state() {
|
139 | return {
|
140 | $any: false,
|
141 | $count: 0,
|
142 | }
|
143 | }
|
144 |
|
145 | start(key) {
|
146 | if (this.state[key]) return false
|
147 | this.setState({
|
148 | [key]: true,
|
149 | $count: this.state.$count + 1,
|
150 | $any: !!(this.state.$count + 1),
|
151 | });
|
152 | }
|
153 |
|
154 | end(key) {
|
155 | this.setState({
|
156 | [key]: false,
|
157 | $count: this.state.$count - 1,
|
158 | $any: !!(this.state.$count - 1),
|
159 | });
|
160 | }
|
161 |
|
162 | run(key, fn) {
|
163 | if (this.state[key]) return false
|
164 | this.start(key);
|
165 |
|
166 | fn(cb => {
|
167 | if (typeof cb === 'function') cb();
|
168 | this.end(key);
|
169 | });
|
170 | }
|
171 | }
|
172 |
|
173 |
|
174 | headless('loading', Loading);
|
175 |
|
176 |
|
177 | headless('fetch', Fetch);
|
178 |
|
179 | return {
|
180 | config,
|
181 | Fetch,
|
182 | };
|
183 | };
|
184 |
|
185 | export default index;
|
186 | export { version };
|
187 |
|