JS Web API Ajax 的核心 API 和使用场景是什么?


JS Web API Ajax 的核心 API 和使用场景

xhr.readyState描述
0(未初始化) 还没有调用 send() 方法
1(载入) 已调用 send() 方法,正在发送请求
2(载入完成) send() 方法执行完成,已经接收到全部的响应内容
3(交互) 正在解析响应内容
4(完成) 响应内容解析完成,可以在客户端调用
xhr.status描述
2xx表示成功处理请求,如 200
3xx需要重定向,浏览器直接跳转,如 301 302 304
4xx客户端错误请求,如 404 403
5xx服务端错误
// GET请求
const xhr = new XMLHttpRequest()
xhr.open('GET', '/data/test.json', true)
xhr.onreadystatechange = function () {
  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)

同源策略

  • ajax 请求时,浏览器要求当前网页和 server 必须同源(安全)
  • 同源:协议、域名、端口,三者必须一致

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

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

JSONP

  • <script> 可绕过跨域限制
  • 服务端可以任意动态拼接数据返回,只要符合 html 格式要求
  • <script> 可以获得跨域的数据,只要服务端愿意返回
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>jsonp 演示</title>
  </head>
  <body>
    <p>一段文字 1</p>
 
    <script>
      window.abc = function (data) {
        console.log(data)
      }
    </script>
    <script src="http://localhost:8002/jsonp.js?username=xxx&callback=abc"></script>
  </body>
</html>
const generateUrl = () => {
    let dataSrc = ''
    for (let key in params) {
      if (params.hasOwnProperty(key)) {
        dataSrc += `${key}=${params[key]}&`
      }
    }
    dataSrc += `callback=${callbackName}`
    return `${url}?${dataSrc}`
  }
  const scriptEl = document.createElement('script')
  scriptEl.src = generateUrl()
  return new Promise((resolve, reject) => {
    document.body.appendChild(scriptEl)
    window[callbackName] = (res) => {
      delete window[callbackName]
      document.body.removeChild(scriptEl)
      if (res) {
        resolve(res)
      } else {
        reject('没有数据')
      }
    }
  })
}