https://www.baidu.com:80/
https://www.baidu.com:8080
// 不同源
/**
* [json 实现ajax的json]
* @param {[type]} options [description]
* @return {[type]} [description]
*/
util.json = function (options) {
var opt = {
url: '',
type: 'get',
data: {},
success: function () {},
error: function () {},
};
util.extend(opt, options);
if (opt.url) {
// ①声明对象,兼容IE
var xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP');
var data = opt.data,
url = opt.url,
type = opt.type.toUpperCase(),
dataArr = [];
for (var k in data) {
dataArr.push(k + '=' + data[k]);
}
// ② 根据请求方式的不同,传递参数的方式也不相同
if (type === 'GET') {
url = url + '?' + dataArr.join('&');
// ③ open方法,确定发送的方式、地址、是否异步
xhr.open(type, url.replace(/\?$/g, ''), true);
// ④ send方法,发送请求
xhr.send();
}
if (type === 'POST') {
xhr.open(type, url, true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(dataArr.join('&'));
}
// ⑤ 监听响应状态变化
xhr.onload = function () {
// ⑥ 处理返回数据, 200表示成功返回 304表示缓存中读取, 如果请求是媒体资源,还需要判断206,因为媒体资源是分段返回的
if (xhr.status === 200 || xhr.status === 304) {
var res;
if (opt.success && opt.success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res);
opt.success.call(xhr, res);
}
}
} else {
if (opt.error && opt.error instanceof Function) {
opt.error.call(xhr, res);
}
}
};
}
};
<script src="http:www.abc.com/?callback=jsonp">script>
3-2 服务端返回数据,全局注册jsonp函数,同时执行本地jsonp函数
<script src="http:www.abc.com/?callback=jsonp">script>
<script>
jsonp({
data: {}
})
script>
代码实现步骤
4-1 确定回调函数的名称
4-2 根据名称注册全局函数
4-3 动态创建scrpit标签
4-4 监听脚本的加载事件
4-5 监听加载是否成功,成功后,删除该script标签,同时删除全局函数
4-6 往html里面新增script标签,发送请求
具体代码实现
/**
* [function jsonp]
* @param {[type]} url [description]
* @param {[type]} onsucess [description]
* @param {[type]} onerror [description]
* @param {[type]} charset [description]
* @return {[type]} [description]
*/
util.jsonp = function (url, onsuccess, onerror, charset) {
var callbackName = util.getName('tt_player');
window[callbackName] = function () {
if (onsuccess && util.isFunction(onsuccess)) {
onsuccess(arguments[0]);
}
};
var script = util.createScript(url + '&callback=' + callbackName, charset);
script.onload = script.onreadystatechange = function () {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = script.onreadystatechange = null;
// 移除该script的 DOM 对象
if (script.parentNode) {
script.parentNode.removeChild(script);
}
// 删除函数或变量
window[callbackName] = null;
}
};
script.onerror = function () {
if (onerror && util.isFunction(onerror)) {
onerror();
}
};
document.getElementsByTagName('head')[0].appendChild(script);
};
// 利用hash,场景是当前页面 A 通过iframe或frame嵌入了跨域的页面 B
// 在A中伪代码如下:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'data';
// 在B中的伪代码如下
window.onhashchange = function () {
var data = window.location.hash;
};
// postMessage
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Awindow.postMessage('data', 'http://B.com');
// 在窗口B中监听
Bwindow.addEventListener('message', function (event) {
console.log(event.origin); // 确定发送的源, http://A.com
console.log(event.source); // A window的引用
console.log(event.data); // data
}, false);
// Websocket【参考资料】http://www.ruanyifeng.com/blog/2017/05/websocket.html
// wss 服务器地址
var ws = new WebSocket('wss://echo.websocket.org');
// 发送请求
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
// 接收消息
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
// 关闭连接
ws.onclose = function (evt) {
console.log('Connection closed.');
};
// CORS【参考资料】http://www.ruanyifeng.com/blog/2016/04/cors.html
// url(必选),options(可选)
fetch('/some/url/', {
method: 'get',
}).then(function (response) {
}).catch(function (err) {
// 出错了,等价于 then 的第二个参数,但这样更好用更直观
});