由“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等请求