12 JS-Web-API-Ajax

347 阅读2分钟

ajax 的核心API - XMLHttpRequest

面试题

- 手写一个简易的ajax
- 跨域常用的实现方式
  • 手写一个简易的ajax
function ajax(url){
    const p = new Promise((resolve,reject)=>{
        const xhr = new XMLHttpRequest()
        xhr.open('GET',url,true)
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4){
                if(xhr.status === 200){
                    resolve(
                        JSON.parse(xhr.responseText)
                    )
                }else if(xhr.status === 404){
                    reject(new Error('404 not found'))
                }
            }
        }
        xhr.send(null)
    })
    return p;
}

const url = '/data/test.json'
ajax(url)
.then(res => console.log(res))
.catch(err => console.log(err))
  • 跨域常用的实现方式
    • JSONP
    • CORS(纯服务端设置)

知识点

  • XMLHttpRequest
  • 状态码
  • 跨域:同源策略,跨域解决方案

XMLHttpRequest

//get请求
const xhr = new XMLHttpRequest()
xhr.open("GET","/api",true) //true是支持异步,false是同步
xhr.onreadystatechange = function(){
    //这里的函数异步执行,可参考之前JS基础中的异步模块
    if(xhr.readyState === 4){
        if(xhr.status === 200){
            console.log(
                JSON.parse(xhr.responseText)
            )
            alert(xhr.responseText)
        }else if(xhr.status === 404){
            console.log('404 not found')
        }
    }
}
xhr.send(null)
//post请求
const xhr = new XMLHttpRequest()
xhr.open("POST","/login",true)//true是支持异步,false是同步
xhr.onreadystatechange = function(){
    //这里的函数异步执行,可参考之前JS基础中的异步模块
    if(xhr.readyState === 4){
        if(xhr.status === 200){
            alert(xhr.responseText)
        }
    }
}
const postData = {
    userName:'zc',
    password:'xxd'
}
xhr.send(JSON.stringify(postData))

xhr.readyState

  • 0 - (未初始化) 还没有调用send()方法
  • 1 - (载入) 已调用send()方法,正在发送请求
  • 2 - (载入完成) send()方法执行完成,已经接收到全部响应内容
  • 3 - (交互) 正在解析响应内容
  • 4 - (完成) 响应内容解析完成,可以在客户端调用 我们也是在状态4的时候才会获取responseText

xhr.status

  • 2xx - 表示成功处理请求,如200
  • 3xx - 需要重定向,浏览器直接跳转,如301 302 304
  • 4xx - 客户端请求错误,如404 403
  • 5xx - 服务器端错误

ajax常用插件工具

  • jQuery
  • fetch
  • axios

什么是浏览器的同源策略

  • 什么是跨域(同源策略)
  • JSONP
  • CORS(服务端支持)

同源策略

  • ajax请求时,浏览器要求当前网页和server必须同源(安全)
  • 同源:协议、域名、端口,三者必须一致
  • 前端:a.com:8080; server:b.com/api/xxx 只是浏览器的要求, 服务器是可以跨域的,比如爬虫

加载图片css js 可无视同源策略

  • <img src=跨域的图片地址/>
  • <link href=跨域的css地址/>
  • <script src=跨域的js地址/></script>
  • <img/>可用于统计打点,可使用第三方统计服务
  • <link/> <script>可使用CDN,CDN一般都是外域
  • <script>可实现JSONP

跨域

  • 所有的跨域,都必须经过server允许和配合
  • 未经server端允许就实现跨域,说明浏览器有漏洞,危险信号

实现跨域的常见方式 - jsonp 和 CORS

  • 访问https://baidu.com/服务端一定返回一个html文件吗?
    • 服务器可以任意动态拼接数据返回,只要符合html格式要求
    • 同理于<script src='https://baidu.com/getData.js>
  • <scrip>可绕过跨域限制
  • 服务器可以任意动态拼接数据返回
  • 所以,<script>就可以获得跨域的数据,只要服务端愿意返回

什么是jsonp

  • 首先,因为ajax无法跨域,然后开发者就有所思考

  • 其次,开发者发现, <script>标签的src属性是可以跨域的,把跨域服务器写成 调用本地的函数 ,回调数据回来不就好了?

  • json刚好被js支持(object)

  • 调用跨域服务器上动态生成的js格式文件(不管是什么类型的地址,最终生成的返回值都是一段js代码)

  • 这种获取远程数据的方式看起来非常像ajax,但其实并不一样

  • 便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP。

  • 传递一个callback参数给跨域服务端,然后跨域服务端返回数据时会将这个callback参数作为函数名来包裹住json数据即可。

//jsonp示例
<script>
window.callback = function(data){
    //这是我们跨域得到的信息
    console.log(data)
}
</script>
<script src='https://baidu.com/getData.js'></script>
<!-- 将返回callback({x:100,y:200}) -->

jQuery实现jsonp

$.ajax({
    url:'http://localhost:8882/api.json',
    dataType:'jsonp',
    jsonpCallback:'callback',
    success:function(data){
        console.log(data)
    }
})

jsonp与AJAX的区别是什么?

  • ajax和jsonp本质上是不同的东西。
  • ajax的核心是通过XmlHttpRequest获取非本页内容
  • jsonp的核心则是动态添加

CORS - 服务器设置http header

通过服务端调置可解决跨域

image.png