示例地址:https://download.csdn.net/download/yzy85/10461053
1、jsonp原理
javascript、ajax访问页面基于同源策略,对于非同一协议、主机或者端口的不同页面,js不能直接访问,会提示跨域访问的错误提示。
为了能够跨域调用函数,需要使用具备跨域属性的方式,而我们知道,html页面引用js文件时,例如<head>标签内的jquery文件,可以通过<script>的src属性引用非同源的文件,此时就能跨域调用,其他有src属性的标签<script>
、<img>
、<iframe>
都能跨域访问其他文件。
因此jsonp的实现核心就是利用script标签的跨域能力,利用提供的url(即动态生成的script标签的src),调用服务器提供的文件或者方法,最终生成返回的都是一段可执行的js代码!
如果要调用非同源的文件获取数据,此时我们可以利用 <script>的标签的这一特性,将后台页面方法生成的json数据存放到返回的文件流中,并利用<script>加载到页面<head>标签内。但是直接返回json数据浏览器不能正确执行,因此还需要将json数据作为参数包含到函数中,当带参数的函数加载到浏览器并解析成功后,浏览器即执行该函数,完成从非同源页面跨域获取数据的过程。
这种利用src属性加载文件调用服务端方法获取数据的方式即是jsonp方式,JSONP 是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback
或者开始就定义一个回调方法,参数给服务端,然后服务端返回数据时会将这个callback
参数作为函数名来包裹住 JSON 数据,返回到浏览器时执行,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
其他解释:jsonp原理:
- 首先在客户端注册一个callback, 然后把callback的名字传给服务器。
- 服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp. 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
- 客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
2、jsonp实现方式
用到的html代码,我们依次测试3种实现方式:
<input type="button" id="btn1" value="点击获取jsonp" οnclick="getJsonp()" /><input type="text" id="txt1" value="" />
<input type="button" id="btn2" value="Jquery点击获取jsonp" /><input type="text" id="txt2" value="" />
<input type="button" id="btn3" value="Jquery($.ajax)点击获取jsonp" /><input type="text" id="txt3" value="" />
<input type="button" id="btn4" value="Jquery($.getScript)点击获取jsonp" /><input type="text" id="txt4" value="" />
C# 后台方法
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
using System.Web.Script.Serialization;
public class Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string studentCode = context.Request.QueryString["code"];
string callback = context.Request.QueryString["callback"];
var msg = new { message = "收到!" };
string result = new JavaScriptSerializer().Serialize(msg);
context.Response.Write(callback + "(" + result + ")");
//context.Response.Write(result);
}
public bool IsReusable
{
get
{
return false;
}
}
}
2.1 javascript原生方式,将url调用直接加入到<script>标签的src属性,然后将<script>加入页面文档中,此时需要提供后台方法需要的参数以及callback页面回调方法,用于包裹返回的json数据。
按钮btn1点击将触发getJsonp函数,增加<script>标签,待返回getBackValue调用,其中getBackValue()函数需要提前定义。
function getBackValue(json) {
document.getElementById("txt").value = json.message;
}
function getJsonp() {
var url = 'Handler.ashx?code=CA1998&callback=getBackValue';
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
}
返回js内容:
2.2、为简化开发,jquery对jsonp进行了封装,封装在了jquery.ajax中函数中。通过定义dataType: 'jsonp'并传递url,参数,回调方法等,执行成功后再success函数中进行下一步处理。其中jsonp参数会包含在get参数中传输到服务器,可以不定义,默认为“callback”,如果定义其它名称,后台方法取get参数的时候也要使用定义的其它名称,jsonpCallback是要回调的函数名称,可定义(返回后直接执行),也可不定义(从jquery提供的默认函数中提取参数在success函数中执行),并且值不能为空,jquery调用完成后会从该函数中提取json数据。
$(function () {
$('#btn2').on('click', function (event) {
event.preventDefault();
$.ajax({
type: 'GET',
async: false,
url: 'Handler.ashx',
data: { "code": "CA1998" },
dataType: 'jsonp',
jsonp: 'callback',//后台QueryString[“callback”],可改为其他字符串
jsonpCallback: 'getBackValue', // 若未定义,默认为jQuery自动生成的随机函数名
success: function (json) {
document.getElementById("txt2").value = json.message;
},
error: function (error) {
alert('fail');
}
});
});
返回内容:
使用该方式调用网络上其他公司提供的api,并且jsonpCallback使用jquery提供的默认值,jquery版本号+随机数字
$('#btn3').bind('click', function (event) {
event.preventDefault();
$.ajax({
type: 'GET',
async: false,
url: 'https://www.sojson.com/open/api/kuaidi/get.shtml',
data: { "orderNo": "887180351164743887" },
dataType: 'jsonp',
jsonp: 'callback',
//jsonpCallback: 'getJsonp', // 默认为jQuery自动生成的随机函数名
success: function (json) {
document.getElementById("txt3").value = json.data[0].info;
},
error: function (error) {
alert('fail');
}
});
});
或者直接使用$.get函数通过jsonp方式调用,返回同上
$('#btn4').bind('click', function (event) {
$.get('https://www.sojson.com/open/api/kuaidi/get.shtml?orderNo=887180351164743887', function (json) {
console.log(json);
document.getElementById("txt4").value = json.data[0].info;
}, 'jsonp');
});
2.3 使用jquery.getScript()函数并传入后台方法参数和回调函数名称,跨域调用Javascript文件并返回调用脚本,返回同上。
$('#btn4').bind('click', function (event) {
event.preventDefault();
$.getScript("https://www.sojson.com/open/api/kuaidi/get.shtml?orderNo=887180351164743887&callback=testjsonp4");
//或者
$.getScript("Handler.ashx?code=CA1998&callback=getBackValue");
});
function testjsonp4(json) {
document.getElementById("txt4").value = json.data[0].info;
}