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. DBA_Oracle Erp R12中文补丁安装升级(案例)

    2014-07-11 Created By BaoXinjian

  2. hdu1358 Period

    首先给个博客:http://blog.csdn.net/lttree/article/details/20732385 感觉他说的很好,尤其是引用的那个博客,清晰的说明了循环节的两个公式. http: ...

  3. 白书 4.1.2 模运算的世界 P291

    1.逆元 这里有个注意事项要说,就是当要求 (a-b)%m 的时候要注意不能直接 (a%m-b%m)%m 原因是得出的值有可能是负数,所以 (a%m-b%m+m)%m 才是正确的. //x,y是引用 ...

  4. Redirect 原理

    mvc .net 中,从服务器端跳转页面有很多方法 有些不会改变浏览器地址栏的地址,这个好理解,mvc本身的机制就是action的名字不一定是view的名字 我们请求的不是文件名,在action中我们 ...

  5. reduce的数目到底和哪些因素有关

      reduce的数目到底和哪些因素有关 1.我们知道map的数量和文件数.文件大小.块大小.以及split大小有关,而reduce的数量跟哪些因素有关呢? 设置mapred.tasktracker. ...

  6. c语言知识(1)

    用freopen重定向输入 freopen函数以指定模式重新指定到另一个文件,模式用于指定新文件的访问方式. FILE *freopen(const char * restrict filename, ...

  7. ruby 字符串学习笔记1

    1 从一种数据结构中构件字符串 hash = { key1: "val1", key2: "val2" } string = "" hash ...

  8. Lua 架构 The Lua Architecture

    转载自:http://magicpanda.net/2010/10/lua%E6%9E%B6%E6%9E%84%E6%96%87%E6%A1%A3/ Lua架构文档(翻译) 十 102010 前段时间 ...

  9. 立体匹配:关于Middlebury提供的源码的简化使用

    Middlebury提供的源码,虽然花了不到一个小时就运行起来啦.但说实话,它那循环读取脚本命令来执行算法真是让我费了不少头脑,花了近三天时间,我才弄明白了它的运行机制.你说,我就想提取一下算法,你给 ...

  10. android 资源文件

    系统文档:http://developer.android.com/guide/topics/resources/available-resources.html 1. 系统下资源文件夹的名字是固定的 ...