由“js跨域”想到"AJAX也不一定要XMLHttpRequest"

关键字:jsonp

jsonp的原理:同源约束限制了js脚本的跨域访问,但是<script>和<iframe>的src标签引用的js文件(只要响应正文是符合js语法的文本即可,不一定是js文件),没有限制。

简述:

浏览器端定义callback函数,名字可以随意,暂且把它就叫callback,然后把改名字传给跨域(刚好可以跨域,也可以是同域,即实现了非XMLHttpRequest也可以ajax),

服务器的响应正文,是callback函数的调用,注意整个正文都需要符合js语法,这样巧妙的实现了跨域。

上代码,自己写的demo,在别人的代码上有改进:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script type="text/javascript">
        var url = "http://www.a.com:8065/Handler1.ashx?c=callback";  //www.a.com本系统目录的hosts中配置下即可,映射到127.0.0.1
        function p(src) {
            //参数r是避免ie浏览器的缓存,在IE中如果短时间请求相同的url,不会从服务器读取,而是从缓存读取
            var u = src + "&r=" + parseInt((Math.random() * 100000000000000000));
            var d = document.createElement("script");
            d.setAttribute("type", "text/javascript");
            d.src = u;
            document.body.appendChild(d);
        }

        function callback(d) { 
            document.getElementById("e").innerHTML = d;
        }

        window.onload = function () {
            p(url);
        };
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>test
        <span id="e"></span>
        <input type="button" value="重新请求" title="重新请求"  onclick="p(url)" />       
    </div>
    </form>
</body>
</html>

www.a.com:8066的handler1.aspx.cs的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApplication1
{
    /// <summary>
    /// Handler1 的摘要说明
    /// </summary>
    public class Handler1 : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "application/javascript";//该值不影响结果
            var c=context.Request["c"];
            context.Response.Write(c + "('" +Guid.NewGuid().ToString()+ "')");//注意传给callbak函数的参数,是js语法,所以要加引号
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

细节都在注释中说明了

仅此备忘

ps:不能取代XMLHttpRequest的是,post和head等请求

posted @ 2014-02-20 13:45  二师弟tl  阅读(2921)  评论(8编辑  收藏  举报