require-node-example
Version:
An example for how to use npm package: require-node & require-node-loader
207 lines (183 loc) • 7.97 kB
JavaScript
;
define(function (require, exports, module) {
//var q = require('q');
module.exports = function () {
//console.log(new Date(), this, arguments);
if (arguments.length < 2) {
throw { msg: '$require arguments.length < 2' };
}
var args = Array.prototype.slice.call(arguments);
args[2] = Array.prototype.slice.call(args[2]);
var moduleName = args[0];
var functionName = args[1];
var actualParams = args[2];
var config = args[3] || {};
var async = !args[4];
var q = config.q;
var url = config.path || '/require-node';
if (config.isDebug) url += '?' + moduleName + '.' + functionName;
var callback = null;
if (typeof actualParams[actualParams.length - 1] === 'function') {
callback = actualParams.pop();
}
var headers = { 'Content-Type': 'application/json', 'X-Require-Node': true };
//添加防止XSRF攻击的http header
var match = window.document.cookie.match(/(?:^|\s|;)XSRF-TOKEN\s*=\s*([^;]+)(?:;|$)/);
if (match) {
headers['X-XSRF-TOKEN'] = match[1];
}
if (async) {
var defer = q.defer();
var handleSuccess = function (result, status, xhr) {
config.isDebug && console.log(arguments);
callback && callback.apply(null, result);
var err = result.shift();
if (err) {
hookError(err);
}
else {
defer.resolve(result.length > 1 ? result : result[0]);
}
}
var handleError = function (err, status, xhr) {
config.isDebug && console.log(arguments);
callback && callback.call(null, err);
hookError(err);
}
var hookError = function (err) {
if (config.reject) {
q().then(function () { return config.reject(err) }).then(defer.resolve, defer.reject);
} else {
defer.reject(err);
}
}
}
var options = {
type: 'POST',
url: url,
headers: headers,
xhrFields: config.xhrFields,
data: JSON.stringify([moduleName, functionName, actualParams]),
async: async,
success: handleSuccess,
error: handleError
}
var ret = _ajax(options);
if (async) {
return defer.promise;
}
else {
var res = JSON.parse(ret.responseText, _formatResponse);
config.isDebug && console.log('sync res:', res);
if (res[0]) {
throw res[0];
}
else {
return res[1];
}
}
function _formatResponse(key, value) {
if (!(value && typeof value === 'object' && value.hasOwnProperty('__$type$__') && value.hasOwnProperty('__$value$__'))) {
return value;
}
switch (value.__$type$__) {
case 'Function':
config.isDebug && console.log(value)
var ret = eval("(function(){return " + value.__$value$__ + " })()");
if (value.__$this$__) {
return ret.bind(value.__$this$__);
} else {
return ret;
}
case 'Date':
return new Date(value.__$value$__);
case 'Map':
return new Map(value.__$value$__);
case 'Set':
return new Set(value.__$value$__);
default:
console.warn('unknown type', value.__$type$__, value)
return value;
}
}
function _ajax(options) {
var xhr = function () {
try { return new XMLHttpRequest(); }
catch (e) {
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) { return new ActiveXObject("Microsoft.XMLHTTP"); }
}
}()
xhr.open(options.type, options.url, options.async);
options.headers = options.headers || {};
for (var header in options.headers) {
xhr.setRequestHeader(header, options.headers[header])
}
options.xhrFields = options.xhrFields || {};
for (var field in options.xhrFields) {
xhr[field] = options.xhrFields[field];
}
var requestDone, status, data, noop = null;
xhr.onreadystatechange = function (isTimeout) {
// The request was aborted
if (!xhr || xhr.readyState === 0 || isTimeout === "abort") {
// Opera doesn't call onreadystatechange before this point
// so we simulate the call
if (!requestDone) {
options.complete && options.complete(data, status, xhr);
}
requestDone = true;
if (xhr) {
xhr.onreadystatechange = noop;
}
// The transfer is complete and the data is available, or the request timed out
}
else if (!requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout")) {
requestDone = true;
xhr.onreadystatechange = noop;
status = isTimeout === "timeout" ?
"timeout" :
!httpSuccess(xhr) ?//really success?
"error" : "success";
var errMsg;
if (status === "success") {
// Watch for, and catch, XML document parse errors
try {
// process the data (runs the xml through httpData regardless of callback)
data = JSON.parse(xhr.responseText, _formatResponse);
}
catch (parserError) {
status = "parsererror";
errMsg = parserError;
}
}
// Make sure that the request was successful or notmodified
if (status === "success" || status === "notmodified") {
// JSONP handles its own success callback
options.success && options.success(data, status, xhr);
}
else {
options.error && options.error(xhr, status, xhr);
}
// Fire the complete handlers
options.complete && options.complete(data, status, xhr);
if (isTimeout === "timeout") {
xhr.abort();
}
}
};
xhr.send(options.data);
return xhr;
}
// Determines if an XMLHttpRequest was successful or not
function httpSuccess(xhr) {
try {
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
return !xhr.status && location.protocol === "file:" ||
xhr.status >= 200 && xhr.status < 300 ||
xhr.status === 304 || xhr.status === 1223;
} catch (e) { }
return false;
}
}
});