再谈jQuery跨任何域

跨域相关的文章老早写过几篇:

jquery url检测遇到的jquery跨域问题及JSONP的使用

PHP - 利用P3P实现跨域

HTTP和HTTPS跨域共享session解决办法

本文是对第一篇的实例补充。

js脚本

$.getJSON
('//sjolzy.cn/?callback=?
&a=1&b=2', function(data) {
    if (typeof(data) == 'object') {
        $.each(data,function(i,j){
            // ...
        });
    }
});

服务端代码

$arr = array("jquery","ajax",array("cross domain","sjolzy.cn"));
$arr['name'] = "kuayu";
echo $_GET['callback'].
"(".json_encode($arr).");";

/* 红色部分是霸气的跨任何域的关键。*/

标签: AJAX, jQuery, 跨域, jsonp

jquery ajax的async参数导致火狐浏览器闪屏

先提下关于jQuery的$.Ajax 的async的作用,

官方的解释是

async Boolean Default: true
By default, all requests are sent asynchronous (e.g. this is set to true by default). If you need synchronous requests, set this option to false. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

async默认是true, 即为异步方式, $.Ajax执行后, 会继续执行ajax后面的脚步, 直到服务器端返回数据后, 触发$.Ajax里的success方法. 这时候执行的是两个线程.

我的出现闪屏
的情况是:

$.ajax({
    type: "post",
    url: "index.php",
    data: { },
    async:false,
    beforeSend:function(){},
    success: function(data){
        //...
    },
    complete:function(){}
});

在这里, 我的async设为了false, 原意是想返回数据了再执行$.Ajax后面的脚本, 没想到这个地方却导致了在火狐浏览器下出现闪屏.(Firefox 11.0), 滚动条下拉到底部触发ajax的情况.闪屏

最后将async:false注释掉, 也就是async为ture的情况下, 成功解决了火狐浏览器滚动条下拉到底部触发ajax出现闪屏的问题.

一段很简洁很棒的原生态javascript的Ajax代码

[代码] [JavaScript]代码

var Ajax={};
Ajax._xmlHttp = function(){ return new (window.ActiveXObject||window.XMLHttpRequest)("Microsoft.XMLHTTP");}
Ajax._AddEventToXHP = function(xhp,fun,isxml){
    xhp.onreadystatechange=function(){
        if(xhp.readyState==4&&xhp.status==200)
            fun(isxml?xhp.responseXML:xhp.responseText);
    }    
}
Ajax.get=function(url,fun,isxml,bool){
    var _xhp = this._xmlHttp();    
    this._AddEventToXHP(_xhp, fun || function(){} ,isxml);
    _xhp.open("GET",url,bool);
    _xhp.send(null);    
}
Ajax.post=function(url,data,fun,isxml,bool){    
    var _xhp = this._xmlHttp();    
    this._AddEventToXHP(_xhp, fun || function(){},isxml);
    _xhp.open("POST",url,bool);
    _xhp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    _xhp.send(data);
}

//demo get 操作
Ajax.get("sjolzy.ajax.html",function(v){
    alert(v)
});

Ajax.get("sjolzy.robots.txt",function(v){
    document.write(v)
});

ajax请求报错Error loading content (NS_ERROR_DOCUMENT_NOT_CACHED)

ajax请求的时候,IE出现拒绝访问的错误,同域名无跨域,调试了半天还是调试不出问题?

FF调试看到错误信息:

Error loading content (NS_ERROR_DOCUMENT_NOT_CACHED)

text/html (NS_ERROR_DOM_BAD_URI)


如果也遇到这种情况,实在想不出啥原因了的话,看看是不是http://和https://的互访。

如果是,协议调一致问题就解决。

标签: AJAX, 跨域, http

Magento Ajax更新购物车

利用Magento插件:SK_CartUpdate
可以很便捷的实现Magento Ajax更新购物车
的功能。见效果图:

Magento Ajax添加产品效果图

点击向上或向下的箭头会弹出遮罩层Ajax更新购物车的数据。

Magento Ajax更新购物车效果图

之后Magento购物车的数据就顺利Ajax更新完成。

这款Magento购物车Ajax更新插件的下载地址:

Magento Connect Version 1:magento-community/SK_CartUpdate

Magento Connect Version 2:http://connect20.magentocommerce.com/community/SK_CartUpdate

ajax问题总结

在看文章前,先指定一个变量xhr,xhr代表ajax对象。

测试浏览器:ie为ie6,firefox为2,其他的未测试。统称ie6为ie,firefox2为ff。

基本的============================================

1,最经典的就是ie下的缓存问题了。
如果使用的是get,那么在ie下出现缓存问题。导致代码只执行一次。解决办法就是加时间戳或者随机数,使url变为唯一,这样就不会出现ie

下的缓存问题了,或者改为post提交。
xhr.open("get","xxxx.aspx?_dc="+new Date().getTime(),true);


2,ajax对象属性的大小写问题
在w3c浏览器,如ff中,对大小写是敏感。如
if(xhr.readystate==4)这种写法,在ie下是成立的,但是在ff下就行不通了,因为ie不区分大小写,ff是区分大小的。
标准写法为if(xhr.readyState==4),同理还有属性 responseText,responseXML,status。
还有状态转换函数xhr.onreadystatechange,要注意全部为小写


3,ajax状态0问题
有些时候在测试ajax代码的时候,加了 xhr.status==200的判断后,一直不执行xhr.status==200的代码,这个就需要注意了。

xhr.status==200是要通过服务器来浏览,并且服务器页面没有发生错误或者转向时才返回200状态的,此状态和你通过浏览器访问页面时服务器定义的状态一致。

直接拖进浏览器浏览结果或者双击运行html页面的,未发生错误时,此时的xhr.status是0,不是200。

所以可以多加一个xhr.status==0的判断。如下

+展开 -JavaScript
if(xhr.status==200||xhr.status==0){
  alert('ok');
}


直接拖进浏览器浏览结果或者双击运行html页面时,又出现一个问题,如果请求的是xml文件,那想当然的是使用responseXML属性返回xmlDom了,但是在ie返回不了xmlDom属性,解决办法如何呢,看下面的responseXML问题。

4,responseXML问题。
要使用responseXML属性,请求的是xml文件或者设置了响应头为"text/xml"的动态页面了。要注意如果请求的是动态页面,一定不要忘记设置contenttype为"text/xml"!!!!!!!!切记~~~~~~

asp为 response.contenttype="text/html"
asp.net为 Response.ContentType="text/html";
php为 header("content-type:text/xml;");

在ie下有个问题,直接拖进浏览器浏览或者双击运行html预览效果时,请求的即使是xml文件,使用responseXML返回不了xmldom。

大家测试下就知道了,如下
showbo.xml

+展开 -XML
<?xml version="1.0" encoding="utf-8"?>
<showbo>
 <item>1</item>
 <item>2</item>
 <item>3</item>
 <item>4</item>
</showbo>

test.html

+展开 -JavaScript
function getajax(){
  if(window.XMLHttpRequest)return new XMLHttpRequest();
  else if(window.ActiveXObject)return new ActiveXObject("microsoft.xmlhttp");
}
var xhr=getajax();
xhr.onreadystatechange=function(){
  if(xhr.readyState==4){
    if(xhr.status==200||xhr.status==0){
      var doc=xhr.responseXML,item=doc.getElementsByTagName("item");
      alert(item.length);//在ie输出为0,在ff下为4。似乎在ie下未生成xml的树结构,具体原因要问ms了。。
    }
    else alert('发生错误\n\n'+xhr.status);
  }
}
xhr.open("get","showbo.xml?_dc="+new Date().getTime(),true);
xhr.send(null);


解决办法就是使用microsoft.xmldom对象重新建立xml的树结构,如下


+展开 -JavaScript
xhr.onreadystatechange=function(){
  if(xhr.readyState==4){
    if(xhr.status==200||xhr.status==0){
      var doc=xhr.responseXML;
      if(document.all&&xhr.status==0){//为ie并且直接托进浏览器的时重构xml的树结构
        doc=new ActiveXObject("microsoft.xmldom");
        doc.loadXML(xhr.responseText);
        doc=doc.documentElement;
      }
      var item=doc.getElementsByTagName("item");
      alert(item.length);
    }
    else alert('发生错误\n\n'+xhr.status);
  }
}


5,为post提交时需要注意的。

1)如果为post提交时,注意要设置content-type为"application/x-www-form-urlencoded",这样在动态页才可以使用request/request.form/request.querystring对象通过键获取值,否则得使用2进制数据,然后自己分析2进制数据生成字符串对象,使用正则什么的获取对应的值。

2)需要在open以后才能使用xhr.setRequestHeader方法,否则出错。
xhr.open("post","xxxx.aspx",true);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");//这里。。。。

 

6.还有一个问题忘记总结了,跨域的问题
如果请求的页面不是当前站点的,那就跨域了,最好的解决方案就是服务器端的xhr请求

可以参考下面的的解决方案
AJAX跨域问题解决办法

不久前放出的一个
使用alexa,google的api获取alexa排名和google  pr,分别使用了客户端和服务器端的xhr请求
中就是使用了服务器端的xhr请求,应为请求的是Google和alexa的页面,所以跨域了,需要使用服务器端的xhr请求。


乱码问题============================================

对于ajax应用来说,乱码也是一个经常出现的问题。
1)meta声明的charset要和请求的页面返回的charset一致。最好在请求的页面中再设置下输出编码。
asp: response.charset="gb2312或者utf-8"
asp.net: response.charset="gb2312或者utf-8"
php: header("charset=gb2312或者utf-8")

2)文件物理存储编码要和meta声明的编码要一致。如meta指定为gb2312,则物理存储编码为ansi。如果为utf-8,则要存储为utf-8编码。

对于asp,如果指定编码为utf-8,记得还要设置

'防止asp使用utf-8编码时中文出现乱码

+展开 -VBScript
Session.CodePage=65001
Response.CharSet="utf-8"

因为asp在国内服务器默认处理编码为gb2312


对于asp.net的话,meta设置为gb2312时,最好设置web.config文件中的

+展开 -XML
<globalization requestEncoding="gb2312" responseEncoding="gb2312"/>

,并且在输出中文前设置Response.CharSet="gb2312";

因为asp.net默认的编码为utf-8

3)发送中文到动态页面时使用escape/encodeURI/encodeURIComponent编码一下。建议使用encodeURIComponent。

更多的js编码信息查看这篇文章

JS URL编码函数

对于php来说,还有个问题,需要在服务器点解码下。可以看这篇文章里面的讨论。

写了一个php查询,但是就是传不出中文。


4)如果1-2都对上了但是在接受服务器端发送的信息时还是出现乱码,试试用XML作为信息载体,然后使用responseXML分析下回传的xml文件。因为ajax原本就是用xml作为信息载体的。。。。。。ajax英文名原本就是“异步javascript和xml”【asynchronous javascript and xml】


如果不会解析xml文件,可以参考这篇文章

JavaScript解析XML的方法总结


下面是一些csdn上出现乱码的文章和解决办法,还未解决的看看,是否和你的如出一辙。

在FireFox浏览器中asp.net+AJAX传输的中文字符串到服务器端后乱码的问题!!!!
请教ajax返回乱码

就列上面两个了,要查找更多的,查看这个查询连接,都是ajax出现乱码的问题。
http://so.csdn.net/bbsSearchResult.aspx?q=ajax+%e4%b9%b1%e7%a0%81&p=0

 


同步问题============================================问题描述如下,问题来自http://topic.csdn.net/u/20090630/16/d4d07596-65da-430c-8e89-cae60e25e03c.html,精简了下创建ajax的代码


+展开 -JavaScript
function callServerByPost(url,data,fun) {
        var http_request=null;    
        if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); 
        }else if (window.XMLHttpRequest)  http_request = new XMLHttpRequest();
        if (!http_request) {
            alert('Giving up :Cannot create an XMLHTTP instance');
            return false;
        } 
        http_request.onreadystatechange = fun; 
        http_request.open("POST", url, true);
        http_request.setrequestheader("Content-length",data.length);
        http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
 
    http_request.send(data);//传送资料
}

function ajax_post(url,data) {
    url=url+"?t="+new Date();
    callServerByPost(url,data,function fns(){        
        if(http_request.readyState == 4) {     
            if (http_request.status == 200) {
                return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到
              } else {
              alert("你请求数据有错");
              }
        }
});   
}

function getData(){
   var url="ajax_server.aspx";
   var data="name=ljp&pwd=ljp";
   var t=ajax_post(url,data);
   alert(t);//在这里弹出undefined =============================
}


为什么会出现这个问题呢??因为在执行getData中的代码var t=ajax_post(url,data);时,由于指定了异步,所以callServerByPost中的http_request.send(data);//传送资料 这句话并不会中断其他js代码的执行,所以会继续执行getData中的下一句代码,就是alert(t),所以会出现undefined。

其实呢并不仅是ajax异步导致出现undefined的问题。认真看下代码var t=ajax_post(url,data);,t变量是接受的是ajax_post的返回值,但是ajax_post函数中并未使用return 返回任何值,所以默认是返回undefined。

你会说我这里不是使用了return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到返回了吗??????????

大家看清楚了,那个是状态转换函数,你返回任何值是没有意义的,他只是处理ajax的状态,你返回值给谁用的呢?????是不是。

如何解决这个问题呢?

一种是改为同步发送
一种就是为异步时使用全局变量来接受ajax的返回值,在状态转换函数中给全局变量赋值。


使用异步+全局变量时要注意的是在ajax未返回前千万不用使用全局变量,要不还是undefined。

下面给出同步的解决办法。异步+全局变量的解决方法看这篇文章

为什么数组作为参数传递进去取不了值出来?


+展开 -JavaScript
function callServerByPost(url,data,fun) {
        var http_request=null;    
        if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); 
        }else if (window.XMLHttpRequest)  http_request = new XMLHttpRequest();
        if (!http_request) {
            alert('Giving up :Cannot create an XMLHTTP instance');
            return false;
        } 
       // http_request.onreadystatechange = fun;  //为同步时不再需要处理函数了。。。。。。。
        http_request.open("POST", url, false);//改为同步
        http_request.setrequestheader("Content-length",data.length);
        http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
 
    http_request.send(data);//传送资料
return http_request.responseText;//同步时可以直接返回,因为会阻止其他的代码执行
}

function ajax_post(url,data) {
    url=url+"?t="+new Date();
    return callServerByPost(url,data,null);//不需要传递回调,并且直接返回callServerByPost的返回值
  
}

function getData(){ 
   var url="ajax_server.aspx";
   var data="name=ljp&pwd=ljp";
   var t=ajax_post(url,data);
   alert(t);//这里就不会输出undefined了。。。。。。。。。。。。,不过如果网路慢的话,浏览器就假死了。。
}


下面这篇是介绍ff和ie状态转换的异同的,有兴趣的参考下

Firefox下的AJAX onreadystatechange问题

 

最后放一个自己写的ajax类库~~~~~O(∩_∩)O哈哈~~~~~完毕


+展开 -JavaScript
String.prototype.trim=function(){return this.replace(/$\s*|\s*$/g,'');}
var Showbo={author:'showbo'};
//获取json对象
Showbo.getJson=function(v){if(typeof(v)=='string')return eval('('+v+')');else return v;}
//根据id获取对象
Showbo.$=function(Id){if('object'==typeof(Id))return Id;else if('string'==typeof(Id))return document.getElementById(Id);else return null;}
Showbo.IsIE=!!document.all;
//扩展IE下的XMLHttpRequest
if(Showbo.IsIE&&!window.XMLHttpRequest)window.XMLHttpRequest=function(){
  var acX=['msxml2.xmlhttp.5.0','msxml2.xmlhttp.4.0','msxml2.xmlhttp.3.0','msxml2.xmlhttp','microsoft.xmlhttp'],Xhr;
  for(var i=0;itry{Xhr=new ActiveXObject(acX[i]);return Xhr;}catch(e){}
  return false;
}
//ajax应用池
Showbo.Ajax={
  pools:[]//存储ajax对象的数组
  ,getObject:function(){//从数组中获取ajax对象,如果未返回则新建一个ajax对象
    for(var i=0;i<this.pools.length;i++)
      if(this.pools[i].readyState==0||this.pools[i].readyState==4)return this.pools[i];
      this.pools[this.pools.length]=new XMLHttpRequest();
      return this.pools[this.pools.length-1];
  }
  ,send:function(cfg){/*cfg示例 
    {
    
url:'请求的页面'
    ,params:'键值对,注意不是json对象'
    ,method:'post/get,如果为指定则默认为get'
    ,success:成功时的回调函数
    ,failure:失败时的回调函数
    ,otherParams:提供给回调函数的其他参数,可以为json对象
    }
   
    成功或者失败的回调函数参数为  (当前的xhr对象,配置文件的中的otherParams)
    */
    if(!cfg||!cfg.url)throw("未设置配置文件!");
    var method=cfg.method,asy="boolean"==typeof(cfg.asy)?cfg.asy:true;
    if(!method||method!="post")method="get";
    if(method.toLocaleLowerCase()=='get'){
      var _dc=new Date().getTime();//加时间戳防止ie浏览器下的缓存
      cfg.params=cfg.params?cfg.params+'&_dc='+_dc:'_dc='+_dc;
      if(cfg.url.indexOf("?")!=-1)cfg.url+="&"+cfg.params;
      else cfg.url+="?"+cfg.params;cfg.params=null;
    }
    else if(!cfg.params)cfg.params='';
    var o=this.getObject();
    if(!o)throw("未能创建ajax对象!");
    o.open(method,cfg.url,asy);
    if(method.toLocaleLowerCase()=='post')o.setRequestHeader("content-type","application/x-www-form-urlencoded");
    o.send(cfg.params);
    o.onreadystatechange=function(){
      if(o.readyState==4){
        if(o.status==200||o.status==0){
          if("function"==typeof(cfg.success))cfg.success(o,cfg.otherParams);
        }
        else if("function"==typeof(cfg.failure))cfg.failure(o,cfg.otherParams);
      }
    }
  }
}

 

 

在responseXML问题。这块中您谈到在“ie输出为0,在ff下为4。似乎在ie下未生成xml的树结构,具体原因要问ms了” 但是我的项目中的结果却是反的,在ie下正常输出为2,ff下始终为0。我仔细检查了大小写都没有问题。ajax的代码为
var xmlHttpRequest;
function createXmlHttpRequest(){
if(window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}
}
function haoLeJiaoWo(){
if(xmlHttpRequest.readyState == 4){
if(xmlHttpRequest.status == 200){
var str = xmlHttpRequest.responseXML;
//解析XML
var inStr="<option>请选择手机型号</option>";
var ele=str.getElementsByTagName("ret");
alert("Array length is"+ele.length);
for(var i=0;i<ele.length;i++)
{
var opt=ele[i].text;
inStr+="<option value="+opt+">"+opt+"</option>";
}
alert(inStr);
document.getElementById("my").innerHTML="<select id=myModel>"+inStr+"</select>";
}
}
}
function show(){
var brand = document.getElementById("myBrand").value;
var url = "/dft/phoneModel.do?operate=getModelByBrand&myBrand=" + brand;
xmlHttpRequest = createXmlHttpRequest();
xmlHttpRequest.onreadystatechange = haoLeJiaoWo;
xmlHttpRequest.open("POST",url,true);
xmlHttpRequest.send(null);
}
但是在ff中输出的结果始终为0 var inStr="<option>请选择手机型号</option>";
var ele=str.getElementsByTagName("ret");
alert("Array length is"+ele.length);

望您给个解答...


管理员回复(2009-7-8 21:56:01)
你生产的xml是什么格式的了?方便的话贴出来看看。
你请求的是动态页,是否设置了相应头为“text/xml”?

并且你可以输出responseText看看是否返回了正确xml格式的字符串


+展开-JavaScript
if(xmlHttpRequest.status == 200){
var str = xmlHttpRequest.responseXML;
alert(xmlHttpRequest.responseText)//=========<br/><br/><br/>

标签: 页面, XML, AJAX, utf, status