环境:rails 3.2.8 ruby 1.9.3
ajax技术主要通过web浏览器和服务器之间的异步交互来增强交互效果,在页面无刷新的情况下从服务器端获取数据,并显示给用户
那么如果这个交互的过程非常耗时,浏览器就会一直处理这个ajax请求,此时并发的访问就会受阻
背景:
目前有需要查看N台服务器的运行状态,在试图页面显示执行结果,而在连接服务器并查看运行状态的时候非常耗时
如果不使用ajax,在控制器中可以通过循环服务器的ip,依次获取服务器的状态,最后把所有结果返回试图页面,可以达到我们想要的效果,但是如果服务器的数量很多,那么这个过程就需要用户等待很长时间,才能看到页面的显示结果,而且如果此时又有另外的用户来访问站点,则他的请求都会受阻,需要等服务器处理完前面的请求,才会响应
此时就会想到使用ajax来异步的获取服务器断返回的结果,也就是说,我想实现,连接一个服务器并获取状态后,返回给页面显示,之后再次发送一个ajax请求,来获取下一个服务器的状态,依此类推,查看所有服务器的状态,这里面将查看服务器状态的请求分成N个ajax请求,如果此时并发的访问站点,服务器就可以再ajax请求之间来处理并发的访问,不会造成阻塞(其实也是再服务器处理完一个ajax请求后,再处理,只是这一个ajax请求只需要连接一个服务器,时间相对较短,视觉上不会造成阻塞而已)
【例子】
在控制器中,将要访问的所有服务器的ip传给ajax
def index @products = Product.search(params[:search]).order( sort_column + " " + sort_direction).paginate(:per_page => 5, :page => params[:page]) @ips =["192.168.5.21","192.168.5.22","192.168.5.23","192.168.5.24","192.168.5.25","192.168.5.26","192.168.5.27","192.168.5.28","192.168.5.29"] respond_to do |format| format.html # index.html.erb format.js # index.html.erb format.json { render :json => @products } end end
在试图页面,有一个按钮来触发这个查看的事件,即:当点击按钮的时候,从控制器中得到所有的ip地址,然后传给check 方法,在check方法中发送ajax请求给服务器
<h2>AJAX</h2> <input type="button" onclick="check(<%= @ips.inspect %>)" value="Get Server IP"></input> <div id="myDiv"></div>
在application.js文件中,ajax请求的原理:发送请求后等待服务器返回结果,接受到返回结果后,调用回调函数,来处理页面端显示,这里面注意回调函数的用法,当连接第一个服务器的时候,send_ips(0, ips); 服务器返回结果,调用回调函数,将ip显示在页面中,接着调用了send_ips(a, ips); 来发送第二个ajax请求,直到ips中所有的ip都连接后,结束,这样,页面中就依次显示了服务器的连接状态
function send_ips(a, ips)
{
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");
}
//回调函数
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=ips[a];
a=a+1;
if (a == ips.length){
return ;
}
send_ips(a, ips);
}
}
xmlhttp.open("GET","/products/fun?ip=" + ips[a],true);
xmlhttp.send();
}
function check(ips){ send_ips(0, ips); }
那么,ajax请求发送给了控制器中的fun,并且以服务器的ip为参数,xmlhttp.open("GET","/products/fun?ip=" + ips[a],true); ,也就是说,在fun这个action中,已知服务器的ip,我们就可以在这个action中来连接服务器,并获取服务器的状态,这里使用了sleep 3,最后返回一个随机数来模拟服务器的处理
def fun sleep 3 render :text => rand(10) end
这样,如果两个用户并发的来查看服务器的状态,就不会出现阻塞的情况了,他们都会发送N个ajax请求给服务器,服务器端轮流处理ajax请求,从而使页面的交互性达到最好