Abstact
这些天开始慢慢深入接触到一些 web 前端的知识,当然不只是前端网站的布局设计上面,主要还是在处理一些逻辑上的问题。也就是实验室现在有了个前端脚本混淆的工程,那么写前端代码自然是必不可少的。特别是在前后端数据交互方面的代码编写。这篇文章主要是记录一下对 Ajax 的全局变量赋值问题的解决。
Background
What
ajax是 2004 年才应用于现在的 web 前后端数据交互技术,简单的说就是可以在 javascript 层面实现前后端的交互(虽然这样理解是不确切的,前端 js 的执行是在浏览器这架构上,所以ajax是一种浏览器和后端服务器交互的技术,只是浏览器的脚本语言为 js,所以 ajax 这中技术就被直观为程序员所理解的浏览器提供的 API 形式,也就是xmlhttprequest。)它说白了就是一次发包请求(post get),但是它和以往的请求有点不一样,他可以不请求整个 html 文件来对页面进行刷新,而是发送一个请求,把请求到的数据按需要内嵌到当前 html 中。
Why
那么,为什么会有这个技术?技术的产生,当然是因为人类的需求。试想每次请求都去刷新整个页面,务必会使 web 应用不友好(盲目的等待,不必要的整个页面的加载和刷新),同时会加重网络传输的负担。无论在客户端还是服务端都是持有弊端的。所以ajax技术应运而生。它通过异步的可编程的方式来对页面进行刷新,而这个过程通常对使用者是透明的,也就是说用户一般感受不到这次发包的过程。同时实现了按需请求,可以在后端指定发送内容,避免了一大推的垃圾 html 代码(毫无变化,但是仍旧需要再次传输)。响应速度也会得到很大的提升。
How
比较常用的两种形式:原生javasctript,jequry
原生 javascript1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
xmlhttp = new XMLHttpRequest();//xmlhttp为实例化的XHR对象
//更为兼容的方式是定义一个新的函数
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
/*==========================================================================================================================
============================================================================================================================*/
//调用open,send,等方方法来实现发送一个数据包,注意定义一个状态改变函数,否则这个响应无法实现,就类似一个callback函数一样。
xmlhttp.open("POST", "ajax/form_return.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("data=" + data);
xmlhttp.onreadystatechange = function (){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText);
}
}
更多细节请查阅相关文档
jequry 形式1
2
3
4
5
6
7
8
9
10
11
12
//和原生js相比,jequry对js代码进行了简化和重构,如下一个.ajax对象,里面封装了属性和方法。
var cdata=30;
$.ajax({
url : './ajax/form_return.php',
async : true,
data: {data:cdata},
success: function(data){
alert(data.responseText);//data为实例化XHR对象
}
});
更多的细节和字段含义可以查阅相关文档
这里补充一下 XHR 返回对象的主要属性,XHR 对象就是XMLHttpRequest对象,它返回主要有以下几个属性:1
2
3
4
responseText: 作为响应主体被返回的文本(文本形式)
responseXML: 如果响应的内容类型是'text/xml'或'application/xml',这个属性中将保存着响应数据的XML DOM文档(document形式)
status: HTTP状态码(数字形式)
statusText: HTTP状态说明(文本形式)
Problem
现在到了写这篇文章的正真意义所在了。由于 ajax 是支持异步模式的,考虑一种情况,在支持异步的模式下,如何通过一个状态转移函数给一个全局的变量赋值?
相信写过 ajax 异步请求,并且需要如此操作的程序员都会面临这个在其他语言中就是个函数直接对全局变量进行修改的小问题,在这加入了一步的 ajax 请求有时会变得充满了玄学(其实是笔者初涉 ajax,才把之说为玄学,还请正真理解了 ajax 原理的师傅莫要嘲笑)。
问题代码如下:原生 javascript
前端:1
2
3
4
5
6
7
8
9
10
11
12
13
var date=30;
var result;
xmlhttp.open("POST", "ajax/form_return.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("data=" + data);
xmlhttp.onreadystatechange = function (){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
result=xmlhttp.responseText;
}
}
alert(result);
后端:1
2
3
4
5
6
7
8
9
error_reporting(0);
$Getdata=$_POST["data"];
$response="hello world";
#$Getdata=30;
if($Getdata==30){
echo $response;
}
?>
按我们的理解这里明明应该弹出一个消息框,上面为服务端返回的值hello world,然而实际上是undefined,exuse me?
jequry1
2
3
4
5
6
7
8
9
10
11
var cdata=30;
var result;
$.ajax({
url : './ajax/form_return.php',
async : true,
data: {data:cdata},
success: function(data){
result=data.responseText;
}
});
alert(result);
在这里 result 同样是undefined,excuse me?
Solve
经过一番苦苦寻觅后,现在总结一下可以尝试对全局变量进行赋值的两种思想。
使用 html5 的新特性,利用浏览器 Web Storage,将函数中接收到的值保存到浏览器的 sessionStorage 或 localStorage(两者都可以用来保存一些数据,前者只是对当前页面,会话有效,后者保存在本地,可以页面之间共用)
在 jequry 中把异步模式设置成true,然后把success方法设置成compete(这个设置同步模式的方法在原生 js 里面缺少类似 complete 的方法,所以只对 jequry 还有效)
在子线程中设置同步请求模式,因为之前说过主线程的同步设置是被浏览器所不推荐的。