1、同源策略
當兩個服務器的 源 不完全相同的時候泪掀,無法獲取另一個的數據听绳。不同的頁面,無法相互訪問數據异赫。
1.1 獲取網站的源
window.origin
或
location.origin
1.2 判斷源是否相同
源 = 協(xié)議 + 域名 + 端口號
當協(xié)議椅挣、域名头岔、端口號(完全一致)才是同源,否者都為不同源
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)")
優(yōu)點:操作簡單
缺點:不兼容IE 6 7 8 9
2.2 JSONP
將數據寫入到JS文件中,利用引用JS文件荠列,將數據保存到window上类浪。最后再利用window來獲取JS保存的數據。
優(yōu)點:兼容IE肌似、可以跨域
缺點:因為是通過js的script獲取的费就,所以他不支持post,只可以發(fā)get請求川队。以及沒有AJAX那樣獲取精確的狀態(tài)碼等數據力细。
2.3 服務器中轉
使用自己的服務器作為中轉站,將需要請求的地址固额,發(fā)送給服務端艳汽。服務端不存在跨域問題,可以直接請求數據对雪。返回給我們自己河狐。
中轉服務器
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__&' + query
script.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))