参考以下几条
(8条消息) 简单的跨域案例_sleepwalker_1992的专栏-CSDN博客
(8条消息) jsonp的使用,解决跨域资源引起CORB问题_D_R_L_T的博客-CSDN博客
(9条消息) 轻松搞定JSONP跨域请求_诗渊的博客-CSDN博客_jsonp
jQuery jsonp跨域请求 - bojiangzhou - 博客园 (cnblogs.com)
跨域的实现与前端和服务器端都有关,根据服务端返回数据的类型而不同前端处理也不同
经过测试,服务端不同,返回数据不同,有json格式,有js对象格式,有的需要跨域,而有的不需要配置跨域就可以访问,下面列举了一些例子
例子一:返回json格式
访问失败
例子二:返回js对象格式
访问失败
对于返回json格式的数据,服务器不支持跨域,前端也没有办法实现,所以跨域是需要前后端同时支持的
jsonp
jsonp是一种跨域解决方式
其原意是指在json数据两端加一个括号前面加一个名称把json封装成一个对象来解决跨域问题
假设客户期望返回数据:["customername1","customername2"]。
真正返回到客户端的数据显示为: callbackFunction(["customername1","customername2"])。
一般来说大多数api都已经支持跨域,请求在请求连接后加上&cb(&callback)变量名就会返回一个js对象
实现有两种
1.例如上面的淘宝
这种是返回jsonp,绝大多数是这种
2.这种是返回一个js变量,这种很少
对于这种的实现方式是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const script = document.createElement("script");
//2 设置标签的src属性
script.src = "http://hq.sinajs.cn/list=sh601006";
//3 将script插入文档中
document.body.appendChild(script);
console.log("before onload")
window.onload = function () {
console.log("after onload")
console.log(hq_str_sh601006);
};
</script>
</body>
</html>
原理是引入标签后,在文档中创建了名为hq_str_sh601006的js变量,直接调用即可
前端jsonp实现跨域
本文只针对前端实现跨域,有多种方式,后端默认为jsonp如上的第一种
script实现原生jsonp
这个原理是创建了一个js对象,像函数一样调用即可
这里有多种写法,我还没摸清楚是什么原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const script = document.createElement("script");
script.src = "https://suggest.taobao.com/sug?q=520&callback=haha";
document.body.appendChild(script);
window["haha"] = function (data) {
console.log("写法1");
console.log(data);
};
window.haha=function(res) {
console.log("写法2");
console.log(res);
};
function haha(data){
console.log("写法3");
console.log(data);
}
</script>
</body>
</html>
jq实现jsonp
jq实现script jsonp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
$(document).ready(function () {
// 向头部输入一个脚本,该脚本发起一个跨域请求
$("head").append(
"<script src='https://suggest.taobao.com/sug?q=520&callback=haha'><\/script>"
);
});
function haha(data) {
console.log(data);
}
</script>
</body>
</html>
jq实现jsonp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
$(document).ready(function () {
$.ajax({
url: "https://suggest.taobao.com/sug?q=520",
//也可以像下面这样写,jq会自动在后面加上callback,?后面会自动生成函数名
//url: "https://suggest.taobao.com/sug?q=520&callback=?",
//而对于请求名不是callback的api不能这样写,要替换掉callback,如下api的请求名是cb
//url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=ccf&cb?"
type: "GET",
dataType: "jsonp", //指定服务器返回的数据类型
success: function (data) {//自动执行
console.log(data);
},
});
});
</script>
</body>
</html>
设置回调函数,这样就不会自动生成了,发出去的请求就是callback=showdata
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
function showData(data) {
console.log(data);
}
$(document).ready(function () {
$.ajax({
url: "https://suggest.taobao.com/sug?q=520",
type: "GET",
dataType: "jsonp", //指定服务器返回的数据类型
jsonpCallback: "showData", //指定回调函数名称
success: function (data) {//自动执行
console.log(data);
},
});
});
</script>
</body>
</html>
需要注意的是回调函数会执行,sucess也会执行,总之success是一定会执行的
所有的参数有
$.ajax({
async : true,
url : "https://api.douban.com/v2/book/search",
type : "GET",
dataType : "jsonp", // 返回的数据类型,设置为JSONP方式
jsonp : 'callback', //指定一个请求名来覆盖默认的请求名callback
jsonpCallback: 'handleResponse', //设置回调函数名
success: function(response, status, xhr){
console.log('状态为:' + status + ',状态是:' + xhr.statusText);
console.log(response);
}
});
jq的简单方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<script>
$.getJSON("https://suggest.taobao.com/sug?q=520&callback=?",
function (data) {
console.log(data);}
);
</script>
</body>
</html>
封装一个完整jsonp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>提示词</title>
</head>
<body>
<script>
function JSONP({ url, params, callbackKey, callback }) {
// 唯一 id,不存在则初始化
JSONP.callbackId = JSONP.callbackId || 1;
params = params || {};
// 传递的 callback 名,和下面预留的一致
params[callbackKey] = `JSONP.callbacks[${JSONP.callbackId}]`;
// 不要污染 window
JSONP.callbacks = JSONP.callbacks || [];
// 按照 id 放置 callback
JSONP.callbacks[JSONP.callbackId] = callback;
const paramKeys = Object.keys(params);
const paramString = paramKeys
.map((key) => `${key}=${encodeURIComponent(params[key])}`)
.join("&");
// const paramString = paramKeys
// .map((key) => `${key}=${params[key]}`)
// .join("&");
const script = document.createElement("script");
script.setAttribute("src", `${url}?${paramString}`);
document.body.appendChild(script);
// id 占用,自增
JSONP.callbackId++;
}
JSONP({
url: "https://suggest.taobao.com/sug",
params: {
q: "520",
},
callbackKey: "callback",
callback(result) {
console.log(result);
},
});
JSONP({
url: "https://suggest.taobao.com/sug",
params: {
q: "1314",
},
callbackKey: "callback",
callback(result) {
console.log(result);
},
});
</script>
</body>
</html>
请求成功后的处理
虽然返回的是一个函数可以直接执行,但是一般传的是json数据,所以可以转换为json
var result = JSON.stringify(data);