AJAX和解决跨域

        先来一个经典的手写原生AJAX

let xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                console.log(xhr.response);
            } else {
                console.log('请求失败');
            }
        }
    }
xhr.open('get', 'http://localhost:3000/xuesheng')
xhr.send()

1、什么是AJAX

        AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS XML。 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。 AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

2、AJAX的特点

2.1 优点

  • 可以无需刷新页面而与服务器端进行通信。
  • 允许你根据用户事件来更新部分页面内容。

2.2 缺点

  • 没有浏览历史,不能回退
  • 存在跨域问题(同源)
  • SEO 不友好

3、AJAX的使用

3.1 核心对象

        XMLHttpRequest, AJAX 的所有操作都是通过该对象进行的

3.2 readyState

        xhr对象有一个readyState属性,表示当前处在请求/相应过程的哪个阶段,这个属性有以下值:

  • 0        未初始化        尚未调用open()方法
  • 1        已打开            已调用open()方法,尚未调用send()方法
  • 2        已发送            已调用send()方法,尚未收到响应
  • 3        接受中            已经收到部分响应
  • 4        完成                已经收到所有响应,这里不分失败还是成功,所以需要在判断status值

        每次readyState从一个值变成另一个值都会触发readystatechange事件。

        在收到响应之前如果想取消异步请求,可以调用abort()方法

        xhr.abort()        调用这个方法后,XHR对象会停止触发事件,并阻止访问这个对象上任何与响应相关的属性。

3.3 GET请求

<body>
    <button id="btn">获取</button>
</body>
<script>
    const btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
        let xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                    console.log(xhr.responseText);
                } else {
                    console.log('请求失败');
                }
            }
        }
        xhr.open('get', 'http://localhost:3000/xuesheng')
        xhr.send()         
    })
</script>

    当携带参数时,因为get请求没有请求体,数据都是放置于URL后的

    形如:key=value&key=value  就是query参数的urlencoded编码形式
    形如:/xx/xxx/帅比/20      就是params参数需要在后端路由占位的
        
    //携带query参数
    xhr.open('GET','http://localhost:3000/xuesheng?name=帅比&age=20')   
    
    //携带params参数
    xhr.open('GET','http://localhost:3000/xuesheng/帅比/20')

3.4. POST请求

        post与get方法不同的点在于,post发送的数据可以用params、query或者请求体,一般使用请求体,并且需要设置请求体编码形式相应的请求头。

<body>
    <button id="btn">获取</button>
</body>
<script>
    const btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
        let xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                    console.log(xhr.responseText);
                } else {
                    console.log('请求失败');
                }
            }
        }
        xhr.open('post', 'http://localhost:3000/xuesheng')

        //这里请求体是urlencoded编码格式,这里就要设置好这个请求头
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        xhr.send('name=帅比&age=20')        

        
        //这里请求体是json编码格式
        xhr.setRequestHeader('Content-type', 'application/json')

        const person = { name: '帅比', age: 20 }

        xhr.send(JSON.stringify(person)) //携带json编码形式的请求体参数
    })
</script>

JSON.stringify()方法将()里的 JavaScript 对象或值转换为 JSON 字符串
JSON.parse()方法用来解析()里的 JSON 字符串,构造由字符串描述的 JavaScript 值或对象  

3.5 解决多次重复请求

        这种方法可以用在很多地方解决一些重复发请求的问题,也叫防抖

<body>
    <button id="btn">获取</button>
</body>
<script>
    const btn = document.getElementById('btn')

    let xhr
    let isLoading    //

    btn.addEventListener('click', function () {

        if(isLoading) xhr.abort()    //

        xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {

                    isLoading = false    //

                    console.log(xhr.responseText);
                } else {
                    console.log('请求失败');
                }
            }
        }
        xhr.open('get', 'http://localhost:3000/xuesheng')
        xhr.send()

        isLoading = true    //         

    })
</script>

4、跨域问题

4.1 为什么会有跨域问题

        浏览器为了安全,而采用的同源策略

4.2 什么是同源策略

  1. 同源策略是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript的浏览器都会使用这个策略
  2. web是构建再同源策略基础上的,浏览器只是针对同源策略的一种实现
  3. 所谓同源是指:协议、域名(IP)、端口必须要完全相同

        即:协议、域名(IP)、端口都相同,才能算是在同一个域里

4.3 非同源受到哪些限制?

  • Cookie不能读取

  • DOM无法获得

  • Ajax请求可以发,但是获取不到数据 

4.4 jsonp避免跨域

        要明确的是:jsonp不是一种技术,而是程序员"智慧的结晶"(利用了标签请求资源不受同源策略限制的特点)

        jsonp原理:绕开xhr利用标签请求资源不受同源策略限制的特点,通过动态创建<script>元素并为src属性指定跨域URL实现,传输数据,也只能发get请求。需要前后端配合,前端定义函数,后端调函数传参数,并把传的参数转为json格式。

//前端代码
<body>
    <button id="btn">jsonp获取数据</button>
</body>
<script>
    const btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
        //1、创建script节点
        const scriptNode = document.createElement('script')
        //2、给节点指定src属性
        scriptNode.src = 'http://localhost:3000/xuesheng'
        //3、将节点放入页面
        document.body.appendChild(scriptNode)
        //4、准备好一个函数
        window.lyc = function(a){
            console.log(a);
        }
        //5、移除已经使用过的script节点
        document.body.removeChild(scriptNode)
    })
</script>


//后端处理
app.get('/xuesheng', (request, response) => {
    const { callback } = request.query
    const person = [{ name: '帅比', age: 20 }, { name: '小帅比', age: 22 }]
    response.send(`${callback}(${JSON.stringify(person)})`)
})

4.5 jsonp面试题

json和jsonp有关系吗?

        json是一种存储和交互数据的格式

        jsonp是一种解决跨域的方法(其实是避免跨域)

        有关系是,当使用jsonp时 后端调用前面函数时,传的参数必须转为json字符串

jsonp解决跨域有用到xhr吗?

        不对,根本没用到

jsonp解决跨域有什么缺点?

        需要前后端配合

4.6 CORS解决跨域

        无需前端人员做任何操作

        CORS(Cross-Origin Resource Sharing),跨域资源共享。 CORS 是官方的跨域解决方
案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持
get post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些
源站通过浏览器有权限访问哪些资源。
        
        CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应
以后就会对响应放行。
        详情看官方文档         跨源资源共享(CORS) - HTTP | MDN
        不过有一个中间件是可以帮忙配置响应头的         cors

        安装        npm add cors

        引入        const cors = require(‘cors’)

        使用        app.use(cors())

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值