1、同源策略
当两个服务器的 源 不完全相同的时候,无法获取另一个的数据。不同的页面,无法相互访问数据。
1.1 获取网站的源
window.origin或location.origin
1.2 判断源是否相同
源 = 协议 + 域名 + 端口号
当协议、域名、端口号(完全一致)才是同源,否者都为不同源 http://baidu.com 与 http://www.baidu.com 不同源 http://baidu.com 与 http://qq.com 不同源
2、跨域
为了解决同源策略无法相互访问数据
其中两种跨域的方法:CORS、JSONP
2.1 CORS
在后端设置响应头,提前声明允许谁获取数据。
response.setHeader("Access-Control-Allow-Origin", "允许的源地址,例如(http://baidu.com)")
优点:操作简单 缺点:不兼容IE 6 7 8 9
2.2 JSONP
将数据写入到JS文件中,利用引用JS文件,将数据保存到window上。最后再利用window来获取JS保存的数据。
优点:兼容IE、可以跨域 缺点:因为是通过js的script获取的,所以他不支持post,只可以发get请求。以及没有AJAX那样获取精确的状态码等数据。
2.3 服务器中转
使用自己的服务器作为中转站,将需要请求的地址,发送给服务端。服务端不存在跨域问题,可以直接请求数据。返回给我们自己。
中转服务器
const http = require('http')const url = require('url')http.createServer((req, res) => {let urlObj = url.parse(req.url, true)if (urlObj.pathname === '/bridge') {http.get(urlObj.query.url, req => {let text = ''req.on('data', data => text += data)req.on('end', () => {res.setHeader('Access-Control-Allow-Origin', '*')res.end(text)})})} else {res.writeHead(404, 'Not Found')res.end('not found')}}).listen(8080)
浏览器正常请求即可
fetch('http://localhost:8080/bridge?url=' + encodeURIComponent('http://baidu.com')).then(res => res.text()).then(data => console.log(data))
3、JSONP封装
3.1 方案1
function jsonp(url) {return new Promise((resolve, reject) => {const random = 'JSONCallbackName' + Math.random()window[random] = data => {resolve(data)}const script = document.createElement('script')script.src = `${url}?callback=${random}`script.onload = () => {script.remove()}script.onerror = () => {reject()}document.body.appendChild(script)})}jsonp('访问数据的文件地址').then((data) => {console.log(data)})
3.2 方案2
服务端
const http = require('http')const url = require('url')http.createServer((req, res) => {let urlObj = url.parse(req.url, true)if (urlObj.pathname === '/getWeather') {let data = { city: 'guangzhou', weather: 'sunny' }res.end(`${urlObj.query.callback}(${JSON.stringify(data)})`)} else {res.writeHead(404, 'Not Found')res.end('not found')}}).listen(8080)
客户端
function jsonp(url, data = {}) {return new Promise((resolve, reject) => {window.__jsonp__ = data => resolve(data)let script = document.createElement('script')let query = Object.entries(data).map(a => `${a[0]}=${a[1]}`).join('&')script.src = url + '?callback=__jsonp__&' + queryscript.onerror = () => reject('加载失败')document.head.appendChild(script)document.head.removeChild(script)})}jsonp('http://api.layouwen.com/getWeather.php', { city: '广州' }).then(data => {console.log(data)}).catch(e => console.log(e))
