Skip to content

Commit 1a287cd

Browse files
committed
Merge pull request #213 from jysperm/node-ajax
在 Node.js 下用 http/https 模块重新实现 AV._ajax, 取代 xmlhttprequest 模块
2 parents 3eff015 + 9ae3324 commit 1a287cd

File tree

8 files changed

+153
-100
lines changed

8 files changed

+153
-100
lines changed

lib/av.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ var AV = module.exports = {};
1212
AV._ = require('underscore');
1313
AV.VERSION = require('./version');
1414
AV.Promise = require('./promise');
15-
AV.XMLHttpRequest = require('./browserify-wrapper/xmlhttprequest').XMLHttpRequest;
1615
AV.localStorage = require('./localstorage');
1716

1817
// 以下模块为了兼容原有代码,使用这种加载方式。
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
var Promise = require('../promise');
2+
3+
module.exports = function _ajax(method, url, data, success, error) {
4+
var options = {
5+
success: success,
6+
error: error
7+
};
8+
9+
if (useXDomainRequest()) {
10+
return ajaxIE8(method, url, data)._thenRunCallbacks(options);
11+
}
12+
13+
var promise = new Promise();
14+
var handled = false;
15+
16+
var xhr = new XMLHttpRequest();
17+
xhr.onreadystatechange = function() {
18+
if (xhr.readyState === 4) {
19+
if (handled) {
20+
return;
21+
}
22+
handled = true;
23+
24+
if (xhr.status >= 200 && xhr.status < 300) {
25+
var response;
26+
try {
27+
response = JSON.parse(xhr.responseText);
28+
} catch (e) {
29+
promise.reject(e);
30+
}
31+
if (response) {
32+
promise.resolve(response, xhr.status, xhr);
33+
}
34+
} else {
35+
promise.reject(xhr);
36+
}
37+
}
38+
};
39+
xhr.open(method, url, true);
40+
xhr.setRequestHeader("Content-Type", "text/plain"); // avoid pre-flight.
41+
xhr.send(data);
42+
return promise._thenRunCallbacks(options);
43+
};
44+
45+
function useXDomainRequest() {
46+
if (typeof(XDomainRequest) !== "undefined") {
47+
// We're in IE 8+.
48+
if ('withCredentials' in new XMLHttpRequest()) {
49+
// We're in IE 10+.
50+
return false;
51+
}
52+
return true;
53+
}
54+
return false;
55+
}
56+
57+
function ajaxIE8(method, url, data) {
58+
var promise = new Promise();
59+
var xdr = new XDomainRequest();
60+
xdr.onload = function() {
61+
var response;
62+
try {
63+
response = JSON.parse(xdr.responseText);
64+
} catch (e) {
65+
promise.reject(e);
66+
}
67+
if (response) {
68+
promise.resolve(response);
69+
}
70+
};
71+
xdr.onerror = xdr.ontimeout = function() {
72+
// Let's fake a real error message.
73+
var fakeResponse = {
74+
responseText: JSON.stringify({
75+
code: AV.Error.X_DOMAIN_REQUEST,
76+
error: "IE's XDomainRequest does not supply error info."
77+
})
78+
};
79+
promise.reject(xdr);
80+
};
81+
xdr.onprogress = function() {};
82+
xdr.open(method, url);
83+
xdr.send(data);
84+
return promise;
85+
}

lib/browserify-wrapper/ajax.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
3+
var http = require('http');
4+
var https = require('https');
5+
var url = require('url');
6+
7+
var Promise = require('../promise');
8+
var AV_VERSION = require('../version')
9+
10+
// `keepAlive` option only work on Node.js 0.12+
11+
var httpAgent = new http.Agent({keepAlive: true});
12+
var httpsAgent = new https.Agent({keepAlive: true});
13+
14+
module.exports = function _ajax(method, resourceUrl, data, success, error) {
15+
var parsedUrl = url.parse(resourceUrl);
16+
var promise = new Promise();
17+
18+
var transportModule = http;
19+
var transportAgent = httpAgent;
20+
21+
if (parsedUrl.protocol === 'https:') {
22+
transportModule = https;
23+
transportAgent = httpsAgent;
24+
}
25+
26+
var req = transportModule.request({
27+
method: method,
28+
protocol: parsedUrl.protocol,
29+
hostname: parsedUrl.hostname,
30+
port: parsedUrl.port,
31+
path: parsedUrl.path,
32+
agent: transportAgent,
33+
headers: {
34+
'Content-Type': 'text/plain',
35+
'User-Agent': 'AV/' + AV_VERSION + ' (Node.js' + process.version + ')'
36+
}
37+
});
38+
39+
req.on('response', function(res) {
40+
var responseText = '';
41+
42+
res.on('data', function(chunk) {
43+
responseText += chunk.toString();
44+
});
45+
46+
res.on('end', function() {
47+
try {
48+
promise.resolve(JSON.parse(responseText), res.statusCode, res);
49+
} catch (err) {
50+
promise.reject(err);
51+
}
52+
});
53+
});
54+
55+
req.on('error', function(err) {
56+
promise.reject(err);
57+
});
58+
59+
req.end(data);
60+
return promise._thenRunCallbacks({
61+
success: success,
62+
error: error
63+
});
64+
}

lib/browserify-wrapper/upload-browser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module.exports = function upload(file, AV, saveOptions) {
2222
var promise = new AV.Promise();
2323
var handled = false;
2424

25-
var xhr = new AV.XMLHttpRequest();
25+
var xhr = new XMLHttpRequest();
2626

2727
if (xhr.upload) {
2828
xhr.upload.onprogress = saveOptions.onProgress;

lib/browserify-wrapper/xmlhttprequest-browser.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

lib/browserify-wrapper/xmlhttprequest.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

lib/utils.js

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -246,95 +246,7 @@ module.exports = function(AV) {
246246
return new Date(Date.UTC(year, month, day, hour, minute, second, milli));
247247
};
248248

249-
AV._ajaxIE8 = function(method, url, data) {
250-
var promise = new AV.Promise();
251-
var xdr = new XDomainRequest();
252-
xdr.onload = function() {
253-
var response;
254-
try {
255-
response = JSON.parse(xdr.responseText);
256-
} catch (e) {
257-
promise.reject(e);
258-
}
259-
if (response) {
260-
promise.resolve(response);
261-
}
262-
};
263-
xdr.onerror = xdr.ontimeout = function() {
264-
// Let's fake a real error message.
265-
var fakeResponse = {
266-
responseText: JSON.stringify({
267-
code: AV.Error.X_DOMAIN_REQUEST,
268-
error: "IE's XDomainRequest does not supply error info."
269-
})
270-
};
271-
promise.reject(xdr);
272-
};
273-
xdr.onprogress = function() {};
274-
xdr.open(method, url);
275-
xdr.send(data);
276-
return promise;
277-
};
278-
279-
AV._useXDomainRequest = function() {
280-
if (typeof(XDomainRequest) !== "undefined") {
281-
// We're in IE 8+.
282-
if ('withCredentials' in new XMLHttpRequest()) {
283-
// We're in IE 10+.
284-
return false;
285-
}
286-
return true;
287-
}
288-
return false;
289-
};
290-
291-
AV._ajax = function(method, url, data, success, error) {
292-
var options = {
293-
success: success,
294-
error: error
295-
};
296-
297-
if (AV._useXDomainRequest()) {
298-
return AV._ajaxIE8(method, url, data)._thenRunCallbacks(options);
299-
}
300-
301-
var promise = new AV.Promise();
302-
var handled = false;
303-
304-
var xhr = new AV.XMLHttpRequest();
305-
xhr.onreadystatechange = function() {
306-
if (xhr.readyState === 4) {
307-
if (handled) {
308-
return;
309-
}
310-
handled = true;
311-
312-
if (xhr.status >= 200 && xhr.status < 300) {
313-
var response;
314-
try {
315-
response = JSON.parse(xhr.responseText);
316-
} catch (e) {
317-
promise.reject(e);
318-
}
319-
if (response) {
320-
promise.resolve(response, xhr.status, xhr);
321-
}
322-
} else {
323-
promise.reject(xhr);
324-
}
325-
}
326-
};
327-
xhr.open(method, url, true);
328-
xhr.setRequestHeader("Content-Type", "text/plain"); // avoid pre-flight.
329-
if (AV._isNode) {
330-
// Add a special user agent just for request from node.js.
331-
xhr.setRequestHeader("User-Agent",
332-
"AV/" + AV.VERSION +
333-
" (NodeJS " + process.versions.node + ")");
334-
}
335-
xhr.send(data);
336-
return promise._thenRunCallbacks(options);
337-
};
249+
AV._ajax = require('./browserify-wrapper/ajax');
338250

339251
// A self-propagating extend function.
340252
AV._extend = function(protoProps, classProps) {

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"dependencies": {
1414
"localstorage-memory": "^1.0.1",
1515
"qiniu": "6.1.3",
16-
"underscore": "^1.8.3",
17-
"leancloud-xmlhttprequest": "^1.8.0"
16+
"underscore": "^1.8.3"
1817
},
1918
"devDependencies": {
2019
"browserify": "^11.0.1",
@@ -41,8 +40,8 @@
4140
},
4241
"browser": {
4342
"react-native": false,
43+
"./lib/browserify-wrapper/ajax.js": "./lib/browserify-wrapper/ajax-browser.js",
4444
"./lib/browserify-wrapper/upload.js": "./lib/browserify-wrapper/upload-browser.js",
45-
"./lib/browserify-wrapper/xmlhttprequest.js": "./lib/browserify-wrapper/xmlhttprequest-browser.js",
4645
"./lib/browserify-wrapper/localStorage.js": "./lib/browserify-wrapper/localstorage-browser.js",
4746
"./lib/browserify-wrapper/parse-base64.js": "./lib/browserify-wrapper/parse-base64-browser.js"
4847
}

0 commit comments

Comments
 (0)