ajax的问题
浏览器同源策略
- 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源
- 源 :协议、域名和端口号都相同即为同源,如果有一个不同,就会产生跨域
跨域
如下在同源时,ajax能够正常请求与响应
新建一个新的端口,不同端口之间的请求
jsonp是一种解决跨域的方法
不受同源策略影响的资源的引入
<script src="..."></script>,<img>,<link>,<iframe>
jsonp
JSONP*(JSON with Padding)解决跨域问题;可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
script标签的跨域
通过script标签引入不同源的文件
<script src="http://localhost:4000/getAjax"></script>
这个文件设置响应体
不受跨域的影响
只使用script标签的缺点
- 变量污染
- query传参时不能动态创建变量
动态创建script
动态添加script,注意处理异步问题,需要在创建完成script后再调用
或者在服务端设置回调函数,把函数名写在query里面传递给后端,然后后端再交给前端去执行
如果是传的对象,通过JSON.stringify()转为json格式传给页面显示
封装jsonp
function ajax(options) {
let opts = Object.assign({
method: 'get',
url: '',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
jsonp: "cb",
data: '',
success: function () { }
}, options);
//处理jsonp请求;
if (opts.dataType === "jsonp") {
jsonpFn(opts.url, opts.data, opts.jsonp, opts.success);
return false;
}
function jsonpFn(url, data, cbName, cbFn) {
// cbName cb/callback
let fnName = "KKB_" + Math.random().toString().substr(2);
window[fnName] = cbFn;
let path = url + "?" + objToQuery(data) + "&" + cbName + "=" + fnName;
// console.log(path);
let o = document.createElement("script");
o.src = path;
document.querySelector("head").appendChild(o);
}
let xhr = new XMLHttpRequest();
if (options.method == "get") {
let data = objToQuery(opts.data);
options.url = options.url + "?" + data;
}
xhr.open(options.method, options.url, true);
for (let key in opts.headers) {
xhr.setRequestHeader(key, opts.headers[key]);
}
let sendData;
switch (opts.headers['content-type']) {
case 'application/x-www-form-urlencoded':
sendData = objToQuery(opts.data);
break;
case 'application/json':
sendData = JSON.stringify(opts.data);
break;
}
xhr.onload = function () {
let resData;
if (xhr.getResponseHeader("content-type").includes("xml")) {
resData = xhr.responseXML;
} else {
resData = JSON.parse(xhr.responseText);
}
options.success(resData);
};
if (options.method == "get") {
xhr.send();
} else {
xhr.send(sendData);
}
}
function objToQuery(obj) {
let res = ``;
for (let key in obj) {
let val = obj[key];
res += `${key}=${val}&`;
}
// 去除末尾的&
return res.slice(0, -1);
}