这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要为大家详细介绍了原生 JS 发送异步数据请求的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
在做项目的时候,有时候需要用到异步数据请求,但是如果这个时候没有框架的依赖,就需要用到原生 JS 进行异步数据请求。这时候无非有两种请求方式,一种是 AJAX,另一个是 JSONP。通过原生 JS 对异步请求进行简单的封装。
AJAX
AJAX 是一种数据请求方式,不需要刷新整个页面就能够更新局部页面的数据。AJAX 的技术核心是 XMLHttpRequest 对象,主要请求过程如下:
不说话直接贴代码
- /**
- * 通过JSON的方式请求
- * @param {[type]} params [description]
- * @return {[type]} [description]
- */
- ajaxJSON(params) {
- params.type = (params.type || 'GET').toUpperCase();
- params.data = params.data || {};
- var formatedParams = this.formateParams(params.data, params.cache);
- var xhr;
- //创建XMLHttpRequest对象
- if (window.XMLHttpRequest) {
- //非IE6
- xhr = new XMLHttpRequest();
- } else {
- xhr = new ActiveXObject('Microsoft.XMLHTTP');
- }
- //异步状态发生改变,接收响应数据
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4 && xhr.status == 200) {
- if ( !! params.success) {
- if (typeof xhr.responseText == 'string') {
- params.success(JSON.parse(xhr.responseText));
- } else {
- params.success(xhr.responseText);
- }
- }
- } else {
- params.error && params.error(status);
- }
- }
- if (params.type == 'GET') {
- //连接服务器
- xhr.open('GET', ( !! formatedParams ? params.url + '?' + formatedParams: params.url), true);
- //发送请求
- xhr.send();
- } else {
- //连接服务器
- xhr.open('POST', params.url, true);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- //发送请求
- xhr.send(formatedParams);
- }
- },
- /**
- * 格式化数据
- * @param {Obj} data 需要格式化的数据
- * @param {Boolean} isCache 是否加入随机参数
- * @return {String} 返回的字符串
- */
- formateParams: function(data, isCache) {
- var arr = [];
- for (var name in data) {
- arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
- }
- if (isCache) {
- arr.push('v=' + (new Date()).getTime());
- }
- return arr.join('&');
- }
IE7 及其以上版本中支持原生的 XHR 对象,因此可以直接用:var oAjax = new XMLHttpRequest();。IE6 及其之前的版本中,XHR 对象是通过 MSXML 库中的一个 ActiveXObject 对象实现的。
通过 xhr 的 open 函数来连接服务器,主要接收三个参数:请求方式、请求地址和是否异步请求(一般都是异步请求)。请求方式有两种,GET 和 POST,GET 是通过 URL 将数据提交到服务器的,POST 则是通过将数据作为 send 方法的参数发送到服务器。
给 xhr 绑定状态改变函数 onreadystatechange,主要用来检测 xhr 的 readyState 的变化,当异步发送成功后,readyState 的数值会由 0 变成 4,同时触发 onreadystatechange 事件。readyState 的属性及对应状态如下:
0 (未初始化) 对象已建立,但是尚未初始化(尚未调用 open 方法)
1 (初始化) 对象已建立,尚未调用 send 方法
2 (发送数据) send 方法已调用,但是当前的状态及 http 头未知
3 (数据传送中) 已接收部分数据,因为响应及 http 头不全,这时通过 responseBody 和 responseText 获取部分数据会出现错误
4 (完成) 数据接收完毕, 此时可以通过通过 responseBody 和 responseText 获取完整的回应数据
在 readystatechange 事件中,先判断响应是否接收完成,然后判断服务器是否成功处理请求,xhr.status 是状态码,状态码以 2 开头的都是成功,304 表示从缓存中获取,上面的代码在每次请求的时候都加入了随机数,所以不会从缓存中取值,故该状态不需判断。
JSONP
如果还是用上面的 XMLHttpRequest 对象来发送需要跨域的请求,虽然调用了 send 函数,但是 xhr 的状态一直都是 0,也不会触发 onreadystatechange 事件,这个时候就要用到 JSONP 的请求方式了。
JSONP(JSON with Padding) 是一种跨域请求方式。主要原理是利用了 script 标签可以跨域请求的特点,由其 src 属性发送请求到服务器,服务器返回 js 代码,网页端接受响应,然后就直接执行了,这和通过 script 标签引用外部文件的原理是一样的。
JSONP 由两部分组成:回调函数和数据,回调函数一般是由网页端控制,作为参数发往服务器端,服务器端把该函数和数据拼成字符串返回。
比如网页端创建一个 script 标签,并给其 src 赋值为 http://www.test.com/json/?callback=process, 此时网页端就发起一个请求。服务端将要返回的数据拼作为函数的参数传入,服务端返回的数据格式类似 "process({'name:'xieyufei'})",网页端接收到了响应值,因为请求者是 script,所以相当于直接调用 process 方法,并且传入了一个参数。
不说话直接贴代码。
- /**
- * 通过JSONP的方式请求
- * @param {[type]} params [description]
- * @return {[type]} [description]
- */
- ajaxJSONP(params) {
- params.data = params.data || {};
- params.jsonp = params.jsonp || 'callback';
- // 设置传递给后台的回调参数名和参数值
- var callbackName = 'jsonp_' + (new Date()).getTime();
- params.data[params.jsonp] = callbackName;
- var formatedParams = this.formateParams(params.data, params.cache);
- //创建script标签并插入到页面中
- var head = document.getElementsByTagName('head')[0];
- var script = document.createElement('script');
- head.appendChild(script);
- //创建jsonp回调函数
- window[callbackName] = function(json) {
- head.removeChild(script);
- clearTimeout(script.timer);
- window[callbackName] = null;
- params.success && params.success(json);
- };
- //发送请求
- script.src = ( !! formatedParams ? params.url + '?' + formatedParams: params.url);
- //为了得知此次请求是否成功,设置超时处理
- if (params.time) {
- script.timer = setTimeout(function() {
- window[callbackName] = null;
- head.removeChild(script);
- params.error && params.error({
- message: '超时'
- });
- },
- params.time);
- }
- }
给 script 标签设置 src 属性时浏览器就会去发送请求,但是只能发送一次请求,导致 script 标签不能复用,因此每次操作完都需要把 script 标签移除。在浏览器发送请求之前给全局绑定一个回调函数,当数据请求成功时就会调用这个回调函数。
总结
将两种发送异步数据的方式整合起来,根据 dataType 来进行判断选用哪种方式。贴上完整的代码
- var xyfAjax = {
- ajax: function(params) {
- params = params || {};
- params.cache = params.cache || false;
- if (!params.url) {
- throw new Error('参数不合法');
- }
- params.dataType = (params.dataType || 'json').toLowerCase();
- if (params.dataType == 'jsonp') {
- this.ajaxJSONP(params);
- } else if (params.dataType == 'json') {
- this.ajaxJSON(params);
- }
- },
- /**
- * 通过JSONP的方式请求
- * @param {[type]} params [description]
- * @return {[type]} [description]
- */
- ajaxJSONP(params) {
- params.data = params.data || {};
- params.jsonp = params.jsonp || 'callback';
- // 设置传递给后台的回调参数名和参数值
- var callbackName = 'jsonp_' + (new Date()).getTime();
- params.data[params.jsonp] = callbackName;
- var formatedParams = this.formateParams(params.data, params.cache);
- //创建script标签并插入到页面中
- var head = document.getElementsByTagName('head')[0];
- var script = document.createElement('script');
- head.appendChild(script);
- //创建jsonp回调函数
- window[callbackName] = function(json) {
- head.removeChild(script);
- clearTimeout(script.timer);
- window[callbackName] = null;
- params.success && params.success(json);
- };
- //发送请求
- script.src = ( !! formatedParams ? params.url + '?' + formatedParams: params.url);
- //为了得知此次请求是否成功,设置超时处理
- if (params.time) {
- script.timer = setTimeout(function() {
- window[callbackName] = null;
- head.removeChild(script);
- params.error && params.error({
- message: '超时'
- });
- },
- params.time);
- }
- },
- /**
- * 通过JSON的方式请求
- * @param {[type]} params [description]
- * @return {[type]} [description]
- */
- ajaxJSON(params) {
- params.type = (params.type || 'GET').toUpperCase();
- params.data = params.data || {};
- var formatedParams = this.formateParams(params.data, params.cache);
- var xhr;
- //创建XMLHttpRequest对象
- if (window.XMLHttpRequest) {
- //非IE6
- xhr = new XMLHttpRequest();
- } else {
- xhr = new ActiveXObject('Microsoft.XMLHTTP');
- }
- //异步状态发生改变,接收响应数据
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4 && xhr.status == 200) {
- if ( !! params.success) {
- if (typeof xhr.responseText == 'string') {
- params.success(JSON.parse(xhr.responseText));
- } else {
- params.success(xhr.responseText);
- }
- }
- } else {
- params.error && params.error(status);
- }
- }
- if (params.type == 'GET') {
- //连接服务器
- xhr.open('GET', ( !! formatedParams ? params.url + '?' + formatedParams: params.url), true);
- //发送请求
- xhr.send(null);
- } else {
- //连接服务器
- xhr.open('POST', params.url, true);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- //发送请求
- xhr.send(formatedParams);
- }
- },
- /**
- * 格式化数据
- * @param {Obj} data 需要格式化的数据
- * @param {Boolean} isCache 是否加入随机参数
- * @return {String} 返回的字符串
- */
- formateParams: function(data, isCache) {
- var arr = [];
- for (var name in data) {
- arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
- }
- if (isCache) {
- arr.push('v=' + (new Date()).getTime());
- }
- return arr.join('&');
- }
- }
- xyfAjax.ajax({
- url: 'http://www.xieyufei.com',
- type: 'get',
- //or post
- dataType: 'json',
- //or jsonp
- data: {
- name: 'xyf'
- },
- success: function(data) {
- console.log(data)
- }
- })
来源: http://www.phperz.com/article/17/0812/338783.html