day23 同源策略及JSONP

 

同源策略 ( 浏览器的一种机制 )

概述 :

浏览器为了安全 , 产生的一种同源策略 , 这个策略是为了防止一些恶意的请求 , 保护用户的隐私 .

同源策略主要有三个内容 , 分别为

  • 同协议 ( http / https )

  • 同ip地址 ( 127.0.0.1 表示本机 )

  • 同端口号 ( 80HTTP的 , 443HTTPS的 )

如果不同源就会产生跨域

跨域问题的产生 ( 以下任意一点不同就会跨域 )

  • 协议不一样

  • 端口不一样

  • ip地址不一样

  • 以文件访问 ( 不同的文件资源也会跨域 )

跨域问题的解决

1.前端解决 ( JSONP ) ( 需要后端给的是JSONP的接口 )

2.后端解决 ( 在对应的响应头进行设置 )

3.使用服务器代理 ( proxy )

4.使用websocket ( 走的不是http协议 )

 

JSONP

概述 :

 

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题 . 

然后它是通过script标签不受跨域影响的特性来解决的 , 核心就是对应的请求是服务器自己去请求再将数据通过回调函数传过来 ( 核心请求是get请求 )

简单的jsonp

<script>
    // JSONP就是利用script标签不会受跨域的影响来实现的,通过服务器的回调函数拿到数据再传过来
    // 它会自动执行你传入的回调函数并将结果传递给这个函数,res里面就会执行完这个数据
    function callback(res) {
        console.log(res)
    }
</script>
<!-- wd表示关键词  cb表示回调函数 -->
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?
             wd=miqi&cb=callback">
</script>

JSONP封装

// 封装jsonp
export const jsonp = (url, params, callbackName, callback) => {
    // 遍历参数,判断url内是否存在?
    for (let key in params) {
        if (url.includes('?')) {
            url += `&${key}=${params[key]}`
        } else {
            url += `?${key}=${params[key]}`
        }
    }
    // 随机生成一个函数名并赋给回调函数
    let fnName = 'fn' + Date.now()
    window[fnName] = callback
    // 将回调函数的名字拼接到url上
    url += `&${callbackName}=${fnName}`
    // 创建一个script标签在页面上并设置url属性
    let script = document.createElement('script')
    script.src = url
    document.body.appendChild(script)
    // 创建后触发onload加载事件
    script.onload = () => {
        // 加载完成后删除函数和script标签
        delete window[fnName]
        script.remove()
    }
}

调用

<script type="module">
    //导入jsonp
    import { jsonp } from './00.js'
    var ul=document.querySelector('ul')
    //给input框添加输入触发事件
    document.querySelector('input').oninput = function () {
        //调用
        jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {
            wd: this.value
        },'cb', (res) => {
            console.log(res)
            ul.innerHTML=''
            //渲染
            res.s.forEach((item)=>{
                ul.innerHTML+=`
                    <li>${item}</li>
                    `
            })
        })
    }
</script>

百度搜索案例

// 封装一个jsonp的promise方法
// url地址,参数,回调函数名称
export const jsonp = (url, params, callbackName) => {
    // 直接返回一个promise对象
    return new Promise((resolve, reject) => {
        // 遍历参数,判断url是否存在'?',没有就加上,有就加上后面的数据
        for (let key in params) {
            if (url.includes('?')) {
                url += `&${key}=${params[key]}`
            } else {
                url += `?${key}=${params[key]}`
            }
        }
        // 随机生成函数名
        let fnName = 'fn' + Date.now() + Math.ceil(Math.random() * 21)
        // 把函数加到window上
        window[fnName] = resolve
        // 拼接url地址
        url += `&${callbackName}=${fnName}`
        // 创建script标签并设置url属性再加到页面上
        let script = document.createElement('script')
        script.src = url
        document.body.append(script)
        // 加载完成后就删除函数和标签
        script.onload = () => {
            delete window[fnName]
            script.remove()
        }
        // 有报错就执行reject
        script.onerror = () => {
            reject()
        }
    })
}

调用

<input type="text">
<ul></ul>
<script type="module">
    // 导入jsonp
    import { jsonp } from './00.js'
    let ul = document.querySelector('ul')
    // 给input添加输入就触发事件
    document.querySelector('input').oninput = function () {
        // 调用方法
        jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {
            wd: this.value
        }, 'cb').then((res) => {
            console.log(res)
            // 渲染
            ul.innerHTML = ''
            res.s.forEach((item) => {
                ul.innerHTML += `
                    <li>${item}</li>
                    `
            })
        })
    }
</script>

 

posted @ 2022-11-01 21:09  邱你咋滴  阅读(33)  评论(0)    收藏  举报