发送 JSONP 请求


使用 <script> 元素可以进行 Ajax 传输的原因如下:

  • 不受同源策略的影响
  • 包含 JSON 编码数据的响应会自动解析

这种使用 <script> 元素作为 Ajax 传输的技术叫做 JSONP。

假设你已经写了一个服务,它处理 GET 请求并返回 JSON 编码的数据,同源的文档可以通过 XMLHttpRequest 对象和 JSON.parse(),如果服务器上启用了 CORS,在较新的浏览器上,跨域的文档也可以使用 XMLHttpRequest 享受该服务,在不支持 CORS 的旧版本浏览器中,跨域的文档只能通过 JSONP 访问这个服务。

当通过 <script> 元素调用数据时,响应内容必须用 JavaScript 函数名和圆括号包裹起来。为了可行起见,我们必须告诉以某种方式告诉后端服务,它正在从一个<script>元素调用,必须返回一个 JSONP 响应,这可以通过在 URL 中添加一个查询参数来实现。

在实践中,支持 JSONP 的服务不会强制指定客户端必须实现的回调函数名称,而是使用查询参数的值,允许客户端指定一个函数名,然后使用该函数名去填充响应:

function getJSONP(url, callback) {
    // 为本次请求创建一个唯一的回调函数名称
    var cbnum = "cb" + getJSONP.counter++;
    var cbname = "getJSONP." + cbnum;
    
    // 将回调函数名称以表单编码的形式添加到URL的查询部分
    // 使用jsonp作为参数名(另一些常见的实现使用callback作为参数名)
    if (url.indexOf("?") === -1) {
        url += "?jsonp=" + cbname;
    } else {
        url += "&jsonp=" + cbname;
    }
    
    // 创建 script 元素用于发送请求
    var script = document.createElement("script");
    
    // 调用将被脚本执行的回调函数
    getJSONP[cbnum] = function (response) {
        try {
            callback(response);
        } finally {
            delete getJSONP[cbnum];
            script.parentNode.removeChild(script);
        }
    };
    
    // 立即触发 HTTP 请求
    script.src = url;
    document.body.appendChild(script);
}
    
getJSONP.counter = 0; 

点赞 取消点赞 收藏 取消收藏

<< 上一篇: 使用 XMLHttpRequest(五):跨域 HTTP 请求

>> 下一篇: 基于服务器端推送事件的 Comet 技术