This time I will bring you the implementation of the jQuery ajax function. What are the precautions for the implementation of the jQuery ajax function. The following is a practical case, let's take a look.
Implementation function
Since the ajax method in jq uses the built-in deferred module, it is an implementation of the Promise mode, and we have not talked about it here, so We will not use this mode.
We only define an ajax method, which can simply get, post, and jsonp requests~~
var ajax = function () { // 做一些初始化,定义一些私有函数等 return function () { // ajax主体代码 } }() ajax({ url: myUrl, type: 'get', dataType: 'json', timeout: 1000, success: function (data, status) { console.log(data) }, fail: function (err, status) { console.log(err) } })
The final function of our ajax method is as shown above, very similar to jq. So what are we waiting for, let’s get started.
Overall idea
Our ajax method needs to pass an object into it. In this object we can define some attributes we want, and we will Various attributes must be initialized
//默认请求参数 var _options = { url: null, // 请求连接 type: 'GET', // 请求类型 data: null, // post时请求体 dataType: 'text', // 返回请求的类型,有text/json两种 jsonp: 'callback', // jsonp请求的标志,一般不改动 jsonpCallback: 'jsonpCallback', //jsonp请求的函数名 async: true, // 是否异步 cache: true, // 是否缓存 timeout:null, // 设置请求超时 contentType: 'application/x-www-form-urlencoded', success: null, // 请求成功回调函数 fail: null // 请求失败回调 }
Above we have defined a large series of request-related data, and then we start writing the ajax main function. The current ajax method is like this
var ajax = function () { //默认请求参数 var _options = { url: null, type: 'GET', data: null, dataType: 'text', jsonp: 'callback', jsonpCallback: 'jsonpCallback', async: true, cache: true, timeout:null, contentType: 'application/x-www-form-urlencoded', success: null, fail: null } // ... return function (options) { // ... } }()
We You can think about it. When the ajax method passes an object in, do we need to overwrite the attributes on the initialization_options with the attributes we set on the object? It is definitely necessary. Then let’s write a simple inheritance first, as follows:
var ajax = function () { //默认请求参数 var _options = { url: null, type: 'GET', data: null, dataType: 'text', jsonp: 'callback', jsonpCallback: 'jsonpCallback', async: true, cache: true, timeout:null, contentType: 'application/x-www-form-urlencoded', success: null, fail: null } // 内部使用的继承方法 var _extend = function(target,options) { if( typeof target !== 'object' || typeof options !== 'object' ) { return; } var copy ,clone, name; for( name in options ) { if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) { target[name] = options[name]; } } return target; }; // ... return function (options) { // 没有传参或者没有url,抛出错误 if( !options || !options.url ) { throw('参数错误!'); } // 继承操作 options.type = options.type.toUpperCase(); _extend(options,_options); // ... } }()
In this inheritance method, we inherit the initialized _options to options. Why? Because our _options object is not inside the ajax method, we need to use it, but we cannot change it. If we change it, the ajax method will crash next time. Therefore, we set the properties that the configured options object does not have to their initial values.
Next, are we going to send a request? etc! It seems that the jsonp request is not an xhr request. It seems to be implemented by inserting the request URL as the src value of the script tag into the page body. Oh, by the way, let's process the jsonp request first and then start building the code for the xhr request.
var ajax = function () { //默认请求参数 var _options = { url: null, type: 'GET', data: null, dataType: 'text', jsonp: 'callback', jsonpCallback: 'jsonpCallback', async: true, cache: true, timeout:null, contentType: 'application/x-www-form-urlencoded', success: null, fail: null } // 内部使用的继承方法 var _extend = function(target,options) { if( typeof target !== 'object' || typeof options !== 'object' ) { return; } var copy ,clone, name; for( name in options ) { if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) { target[name] = options[name]; } } return target; }; // jsonp处理函数 function _sendJsonpRequest(url,callbackName,succCallback) { var script = document.createElement('script'); script.type="text/javascript"; script.src=url; document.body.appendChild(script); // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数 window[callbackName] = window[callbackName] || succCallback; } // ... return function (options) { // 没有传参或者没有url,抛出错误 if( !options || !options.url ) { throw('参数错误!'); } // 继承操作 options.type = options.type.toUpperCase(); _extend(options,_options); /*jsonp部分,直接返回*/ if( options.dataType === 'jsonp' ) { var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url + '?' + options.jsonp+ '=' + options.jsonpCallback; return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success); } // ... } }()
We have defined a _sendJsonpRequest function. This function receives three parameters. The first is jsonpUrl, the second is the callback function name of jsonp, and the third is the success callback function. We are in this function Create a script element with src as jsonpUrl and insert it into the body. At the same time, determine the callback function (if we define the jsonpCallback function, call it, if not, call the success callback. Generally, we do not define the global jsonpCallback function and pass it success callback to complete the jsonp request).
Okay, after processing the jsonp request, we start processing the xhr request.
var ajax = function () { //默认请求参数 var _options = { url: null, type: 'GET', data: null, dataType: 'text', jsonp: 'callback', jsonpCallback: 'jsonpCallback', async: true, cache: true, timeout:null, contentType: 'application/x-www-form-urlencoded', success: null, fail: null } // 内部使用的继承方法 var _extend = function(target,options) { if( typeof target !== 'object' || typeof options !== 'object' ) { return; } var copy ,clone, name; for( name in options ) { if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) { target[name] = options[name]; } } return target; }; // jsonp处理函数 function _sendJsonpRequest(url,callbackName,succCallback) { var script = document.createElement('script'); script.type="text/javascript"; script.src=url; document.body.appendChild(script); // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数 window[callbackName] = window[callbackName] || succCallback; } // json转化为字符串 var _param = function(data) { var str = ''; if( !data || _empty(data)) { return str; } for(var key in data) { str += key + '='+ data[key]+'&' } str = str.slice(0,-1); return str; } //判断对象是否为空 var _empty = function(obj) { for(var key in obj) { return false; } return true; } // ... return function (options) { // 没有传参或者没有url,抛出错误 if( !options || !options.url ) { throw('参数错误!'); } // 继承操作 options.type = options.type.toUpperCase(); _extend(options,_options); /*jsonp部分,直接返回*/ if( options.dataType === 'jsonp' ) { var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url + '?' + options.jsonp+ '=' + options.jsonpCallback; return _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success); } //XMLHttpRequest传参无影响 var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP'); // get搜索字符串 var search = ''; // 将data序列化 var param= _param(options.data) if( options.type === 'GET' ) { search = (options.url.indexOf('?') > -1 ? '&' : '?') + param; if(!options.cache) { search += '&radom='+Math.random(); } param = null; } // ... } }()
First of all, it is compatible with IE to create xhr objects. XMLHttpRequestConstructorPassing parameters has no effect. Then we define two auxiliary variables: search and param. The former is used for query of get request. String, the latter is used for the send content of the post request. We have defined a _param method to convert the object into the send method parameter mode. As you can see, below we have made a reasonable transition between get and post. Assignment work of search and param. Next we can send a request to write the most exciting content.
The final code is as follows
; var ajax = function () { //默认请求参数 var _options = { url: null, type: 'GET', data: null, dataType: 'text', jsonp: 'callback', jsonpCallback: 'jsonpCallback', async: true, cache: true, timeout:null, contentType: 'application/x-www-form-urlencoded', success: null, fail: null } // json转化为字符串 var _param = function(data) { var str = ''; if( !data || _empty(data)) { return str; } for(var key in data) { str += key + '='+ data[key]+'&' } str = str.slice(0,-1); return str; } //判断对象是否为空 var _empty = function(obj) { for(var key in obj) { return false; } return true; } var _extend = function(target,options) { if( typeof target !== 'object' || typeof options !== 'object' ) { return; } var copy ,clone, name; for( name in options ) { if(options.hasOwnProperty(name) && !target.hasOwnProperty(name)) { target[name] = options[name]; } } return target; }; // 自定义text转化json格式 var parseJSON = function(text) { if(typeof text !== 'string') { return; } if( JSON && JSON.parse ) { return JSON.parse(text); } return (new Function('return '+text))(); } // jsonp处理函数 function _sendJsonpRequest(url,callbackName,succCallback) { var script = document.createElement('script'); script.type="text/javascript"; script.src=url; document.body.appendChild(script); // 如果用户自己定义了回调函数,就用自己定义的,否则,调用success函数 window[callbackName] = window[callbackName] || succCallback; } return function (options) { // 没有传参或者没有url,抛出错误 if( !options || !options.url ) { throw('参数错误!'); } // 继承操作 options.type = options.type.toUpperCase(); _extend(options,_options); /*jsonp部分,直接返回*/ if( options.dataType === 'jsonp' ) { var jsonpUrl = options.url.indexOf('?') > -1 ? options.url: options.url + '?' + options.jsonp+ '=' + options.jsonpCallback; _sendJsonpRequest(jsonpUrl,options.jsonpCallback,options.success); return; } //XMLHttpRequest传参无影响 var xhr = new (window.XMLHttpRequest || ActiveXObject)('Microsoft.XMLHTTP'); // get搜索字符串 var search = ''; // 将data序列化 var param= _param(options.data) if( options.type === 'GET' ) { search = (options.url.indexOf('?') > -1 ? '&' : '?') + param; if(!options.cache) { search += '&radom='+Math.random(); } param = null; } xhr.open( options.type, options.url + search, options.async ); xhr.onreadystatechange = function() { if( xhr.readyState == 4 ) { if( xhr.status >= 200 && xhr.status < 300 || xhr.status == 304 ) { var text = xhr.responseText; // json格式转换 if(options.dataType == 'json') { text = parseJSON(text) } if( typeof options.success === 'function') { options.success(text,xhr.status) } }else { if(typeof options.fail === 'function') { options.fail('获取失败', 500) } } } } xhr.setRequestHeader('content-type',options.contentType); // get请求时param时null xhr.send(param); // 如果设置了超时,就定义 if(typeof options.timeout === 'number') { // ie9+ if( xhr.timeout ) { xhr.timeout = options.timeout; }else { setTimeout(function() { xhr.abort(); },options.timeout) } } } }()
As you can see, we are very familiar with the xhr code. Here, we need to write a method parseJSON that parses the returned string to form a json format object, similar to jq parseJSON method in , as shown above.
We also need to set the timeout code. If the request timeout is set, we define it as above.
Note: In the above code, due to laziness, the line of setting the request header does not determine whether it is under a post request. You can set it yourself~~~.
I believe you have mastered the method after reading the case in this article. For more exciting information, please pay attention to other related articles on the php Chinese website!
Recommended reading:
jQuery Ajax Analysis Collection
Native js implements ajax request method
The above is the detailed content of jQuery+ajax function implementation. For more information, please follow other related articles on the PHP Chinese website!