script请求返回JSON实际上是脚本注入。它虽然解决了跨域问题,但它不是万能的。

  1. 不能接受HTTP状态码
  2. 不能使用POST提交(默认GET)
  3. 不能发送和接受HTTP头
  4. 不能设置同步调用(默认异步)
  5. ...

其最严重的就是不能提供错误处理,如果请求的代码正常执行那么会得到正确的结果。如果请求失败,如404,500之类,那么可能什么都不会发生。这篇在上一篇的基础上将着重解决JSONP的错误处理。

说可能是因为有些浏览器还是可以提供一些错误处理的。如IE9/10/Firefox/Safari/Chrome都支持script的onerror事件,如果请求失败,在onerror上可以进行必要的回调处理。但IE6/7/8/Opera却不支持onerror。这就是令人头疼的地方,打造一个完美的Sjax不太容易。

只要解决了IE6/7/8/Opera的onerror,整个就ok了。思路是逆向思维:请求成功则成功回调,否则就是失败回调。不拿onerror说事,因为它压根没onerror。因此只能那onload说事。就好比以下推论:

“你是对的” 推断出 “你没错”

因为我没办法知道你是“错的”。但我知道你是“对的”,只能拿是否对去推断你是否错了。

最后的实现细节如下:

1,IE9/Firefox/Safari/Chrome 成功回调使用onload事件,错误回调使用onerror事件

2,Opera 成功回调也使用onload事件(它压根不支持onreadystatechange),由于其不支持onerror,这里使用了延迟处理。即等待与成功回调success,success后标志位done置为true。failure则不会执行,否则执行。这里延迟的时间取值很有技巧,之前取2秒,在公司测试没问题。但回家用3G无线网络后发现即使所引用的js文件存在,但由于网速过慢,failure还是先执行了,后执行了success。所以这里取5秒是比较合理的。虽然这种方式间接实现了failure,但不彻底。

3,IE6/7/8成功回调使用onreadystatechange事件,错误回调几乎是很难实现的。令人恶心的是即使请求的资源文件不存在(404)。它的readyState也会经历“loaded”状态。这样你就没法区分请求成功或失败。最后使用前后台一起协调的机制解决最后的这个难题。无论请求成功或失败都让其调用callback(true)。 此时已经将区别成功与失败的逻辑放到了callback中,如果后台没有返回jsonp则调用failure,否则调用success。

接口:

1
2
3
4
5
6
7
Sjax.load(url, {
    data        // 请求参数 (键值对字符串或js对象)
    success     // 请求成功回调函数
    failure     // 请求失败回调函数
    scope       // 回调函数执行上下文
    timestamp   // 是否加时间戳
});

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>sjax_0.3.js by snandy</title>
    <script src="http://files.cnblogs.com/snandy/sjax_0.3.js"></script>
</head>
<body>
<input type="button" value="Get Name" onclick="clk()"/>
<script type="text/javascript">
    function clk(){
        Sjax.load('jsonp66.js', {
            success : function(){alert(jsonp.name)},
            failure : function(){alert('error');}
        });
    }
</script>
</body>
</html>

以上html,点击“Get Name”按钮,调用clk函数。因为请求的资源jsonp66.js压根不存在。各浏览器下都会弹出“error”,当然Opera中会延迟一些。好了,本系列结束。

点击试试

相关:

http://stackoverflow.com/questions/3483919/script-onload-onerror-with-iefor-lazy-loading-problems

https://github.com/snandy/io

分类: Ajax/Fetch

跨域请求之JSONP 三的更多相关文章

  1. JAVAEE——宜立方商城11:sso登录注册功能实现、通过token获得用户信息、Ajax跨域请求(jsonp)

    1. 学习计划 第十一天: 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 4.Ajax跨域请求(jsonp) 2. Sso系统工程搭建 需要创建一个sso服务工程,可 ...

  2. 跨域请求之JSONP 一

    跨域请求之JSONP 一 跨域请求的方式有很多种, iframe document.domain window.name script XDomainRequest (IE8+) XMLHTTPReq ...

  3. js跨域请求(jsonp)

    jsonp是跨域请求的手段之一. jsonp的原理: 先来看看下面这段代码 <!DOCTYPE html> <html lang="en"> <hea ...

  4. 搞定所有的跨域请求问题 jsonp CORS

    网上各种跨域教程,各种实践,各种问答,除了简单的 jsonp 以外,很多说 CORS 的都是行不通的,老是缺那么一两个关键的配置.本文只想解决问题,所有的代码经过亲自实践.   本文解决跨域中的 ge ...

  5. Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域

    JSONP原理及实现 接下来,来实际模拟一个跨域请求的解决方案.后端为Spring MVC架构的,前端则通过Ajax进行跨域访问. 1.首先客户端需要注册一个callback(服务端通过该callba ...

  6. 跨域请求,jsonp

    其实跨域请求,只需要在请求的url后面加上callback=?即可. 提供以下两种获取跨域的ajax的写法,都是基于jQuery.都已经成功使用,兼容做到ie7,(ie6未测试);案例地址来自豆瓣开放 ...

  7. Django跨域请求之JSONP和CORS

    现在来新建一个Django项目server01,url配置为 url(r'^getData.html$',views.get_data) 其对应的视图函数为get_data: from django. ...

  8. Ajax+Spring MVC实现跨域请求(JSONP)(转)

    背景: AJAX向后台(springmvc)发送请求,报错:已阻止交叉源请求:同源策略不允许读取 http://127.0.0.1:8080/DevInfoWeb/getJsonp 上的远程资源.可 ...

  9. 跨域请求:JSONP

    在JavaScript中,有一个很重要的安全性限制,被称为"同源策略".即JavaScript只能访问与包含它的文档在同一域下的内容.然而,当进行一些比较深入的前端编程的时候,不可 ...

随机推荐

  1. [Python] UTF-8最好不要带BOM

    一.问题回顾: 问题: 在写一个脚本读入IP分区表文件到list并做比较的时候,发现该成立的语句总是不成立,经调试后发现开头是这样:\xef\xbb\xbf1.0.3.0,故比较不成功. 解决办法:经 ...

  2. 查看iis错误日志时提示找不到 freb.xsl的解决方法

    http://stackoverflow.com/questions/786638/how-can-i-get-gzip-compression-in-iis7-working/787251 Look ...

  3. 转-安卓中实现两端对齐,中间fill_parent的方法

    安卓中实现两端对齐,中间fill_parent的方法 Java代码:   <?xml version="1.0″ encoding="utf-8″?> <Line ...

  4. js上移、下移、置顶、置底功能实现

    实现页面上列表内容上移.下移.置顶.置底 功能,主要实现思路是节点操作,比如说:上移,直接把点击项移动到前一个节点,以此类推,当然实际代码实现还要加些判断,如当前点击操作项是否已经是置底或置底了,如果 ...

  5. Yii2.0高级框架数据库增删改查的一些操作

    yii2.0框架是PHP开发的一个比较高效率的框架,集合了作者的大量心血,下面通过用户为例给大家详解yii2.0高级框架数据库增删改查的一些操作 --------------------------- ...

  6. Number of Islands

    Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...

  7. centos安装——usb安装技术问题整理

    1) 官网How tohttp://wiki.centos.org/HowTos/InstallFromUSBkey 2)我安装碰到的问题:http://www.douban.com/group/to ...

  8. SQL锁表解决并发性

    在数据库开发过程中,不得不考虑并发性的问题,因为很有可能当别人正在更新表中记录时,你又从该表中读数据,那你读出来的数据有可能就不是你希望得到的数据.可以说有些数据同时只能有一个事物去更新,否则最终显示 ...

  9. Oracle中的约束

    非空约束 NOT NULL 数据库表中的某一个列不能为空 唯一约束 UNIQUE 表中某一个列不允许重复 唯一约束所在列可以为NULL,但只能出现一次 代码: CREATE TABLE MEMBER ...

  10. wait(0)

    public final synchronized void join(long millis) throws InterruptedException { long base = System.cu ...