同源政策
浏览器的同源政策
出于安全性的考虑 他只允许对应的两者是同源的内容进行交互和访问,不同源的内容不允许访问
跨域
1.访问协议不同 http https
2.域名不同 百度 搜狐
3.端口号不同
4.走的file协议 文件不一样也会跨域
解决跨域方法
1.添加请求头 后端添加请求头 access-control-allow-origin:* 跨域地址
2.前端也可以添加请求头:setRequestHeader
3.jsonp形式 利用link script ifarme 这三个标签不受跨域影响 只能解决get请求方式
jsonp基础案例
<script>
function a(str){
console.log(str);
//ajax请求 自己请求自己
}
//给窗口添加一个方法
window["abc"] = a
//相当于这里会自动执行window的abc方法 也就是上面的a方法 将数据填入a方法的形参
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?cb=abc&wd=hello"></script>
jsonp封装
function jsonp({
url,//链接地址
params,//参数 对象类型
callbackName,//回调函数名字
callback,//回调函数
}){
//1.给window添加方法 方法名不能重复
// 随机生成一个函数名
let fnName = 'fn'+Date.now()+Math.ceil(Math.random()*1000)
window [fnName] = callback //传递给.then方法的参数是success来传递
//2.添加script
let script = document.createElement('script')
//3.将方法名拼接到url地址后面
url +=`?${callbackName}=${fnName}`
//4.将参数再做拼接
let paramsStr = joinParams(params)
url +=paramsStr
//5.将这个url地址给script标签
script.src = url
//6.将script加给body
document.body.appendChild(script)
//判断是否已经加载成功
script.onload = function(){
script.remove()
delete window[fnName]
}
}
function joinParams(params){
let str =''
//取出对象里面的值
for(let key in params){
str +=`&${key}=${params[key]}`
return str
}
}
使用promise的jsonp封装
function jsonp({
url,//链接地址
params,//参数 对象类型
callbackName,//回调函数名字
}){
return new Promise((success,error)=>{
//1.给window添加方法 方法名不能重复
// 随机生成一个函数名
let fnName = 'fn'+Date.now()+Math.ceil(Math.random()*1000)
window [fnName] = success //传递给.then方法的参数是success来传递
//2.添加script
let script = document.createElement('script')
//3.将方法名拼接到url地址后面
url +=`?${callbackName}=${fnName}`
//4.将参数再做拼接
let paramsStr = joinParams(params)
url +=paramsStr
//5.将这个url地址给script标签
script.src = url
//6.将script加给body
document.body.appendChild(script)
//判断是否已经加载成功
script.onload = function(){
script.remove()
delete window[fnName]
}
//如果加载出错
script.onerror = function(){
error('加载出问题')
}
})
}
function joinParams(params){
let str =''
//取出对象里面的值
for(let key in params){
str +=`&${key}=${params[key]}`
return str
}
}
async与 await
es7新增了async同步 await 等待 俩个修饰来帮我们解决promise代码冗余的问题
async 他是用来修饰函数的 函数执行他返回的也是一个promise对象,里面东西他可以使用await来修饰 这个修饰也是一个promise对象
async函数可能包含0个或者多个await表达式。await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。
(async function name (){
await fn('张三',3000) //本来是异步执行,现在是同步执行
await fn('李四',2000) //本来是异步执行,现在是同步执行
console.log('吃饭');
//所以是三秒后先打印张三点击了,再2秒后打印李四点击,再打印吃饭
})()
function fn(str,time){
return new Promise((success,error)=>{
setTimeout(()=>{
console.log(str+'点击了');
success()
},time)
})
}
//总结:
// async 是用于修饰函数 返回值是一个promise对象 async替代了promise
// await是async里面一个修饰符 当他修饰一个promise对象的时候 他会获取程序的控制权 直到完成或失败结束
//await替代了promise中的.then
// await关键字只在async函数内有效
使用promise的jsonp制作的例子(百度输入框)
<input type="text">
<ul id="box"></ul>
<script src="./promise.jsonp.js"></script>
<script>
let input = document.querySelector('input')
let box = document.getElementById('box')
var url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su"
input.onkeyup = throttle(function(){
//如果内容为空删除
if(input.value.trim()==''){
box.remove()
return
}
//删除ul及里面内容 在创建一个ul
box.remove()
let ul = document.createElement('ul')
ul.id = 'box'
document.body.appendChild(ul)
box = document.getElementById('box')
//在事件里面进行jsonp请求
let promise = jsonp({
url,
params:{
wd:input.value
},
callbackName:'cb'
})
promise.then((res)=>{
//获取数据(判断数据是否为null)
if(res.s.length !=0){
//遍历数据
for(let v of res.s){
//添加li
let li = document.createElement('li')
li.innerText = v
box.appendChild(li)
//使用事件委托机制,加给父类box
//移进事件
box.onmouseover = function(e){
if(e.target.nodeName=='LI'){//判断是否为li,为box不执行
for(let li of box.children){
li.style.background = ''
}
e = e||window.event
e.target.style.background = 'skyblue'
}
}
//点击事件
box.onclick = function(e){
e = e||window.event
input.value = e.target.innerText
}
}
}
})
},200)
//节流
function throttle(fu,wait){//传入参数 执行的函数,等待时间
let time = null//节流阀
return function(){
if(time){ //null就是false,执行下面的,true直接跳过
return
}
time = setTimeout(()=>{
fu()
time = null//做完后节流阀设置为null
},wait)
}
}
</script>