zoukankan      html  css  js  c++  java
  • 原生ajax & 跨域问题

    前言

    其实一直对原生ajax和跨域的问题似懂非懂,理解的程度也不是很全面,所以打算整理一下知识点,现在一般交互使用现成的插件,也就是调用封装好的api实现交互,出现的问题对应也有解决的方式,,解决跨域问题也是只知道没有出现跨域问题,如何解决的了解的也不是很透彻,虽然现在可能有些方式用的不是很多了,但是了解清楚还是很重要的

    原生ajax讲解 

    ajax即"Asynchronous Javascript And XML"(异步的JavaScript和XML)
    ajax的核心是XMLHTTPRequest对象(XHR)

    先创建一个xhr对象

    function createXHR(){
      let xhr
      if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest()
      }else if(window.ActiveXObject){
        xhr = new ActiveXObject("Microsoft.XMLHTTP")
      }
      return xhr
    }

    XMLHttpRequest 1级

    xhr对象的主要方法

    void open(String method,String url,Boolean async)
    method:请求方式
    url:请求地址
    async:是否异步,默认为true
    username:可选参数,如果服务器需要验证,该参数指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。
    password:可选参数,验证信息中的密码部分,如果用户名为空则改制将被忽略。
     
    void send(String body)
    body:要发送的数据
     
    void setRequestHeader(String header,String value)
    header:请求头的key
    value:请求头的value
     
    String getAllResponseHeaders()
    获得所有响应头,返回值:响应头数据
     
    String getResponseHeader(String header)
    获取响应头中指定header的值
     
    void abort()
    终止请求

    xhr对象的主要属性

    Number readyState 状态值,可以确定请求/响应过程的当前活动阶段
    0:未初始化。未调用send()方法。
    1:启动。已经调用open()方法,但尚未调用send()方法。
    2:发送。已经调用send()方法,但尚未接收到响应。
    3:接收。已经接收到部分响应数据。
    4:完成。已经接收到全部的响应数据,而且可以在客户端使用了。
     
    Function onreadystatechange 当readyState的值改变时自动触发执行其相应的(回调)函数。
    String responseText 作为相应主体被返回的文本
    XMLDocument responseXML 服务器返回的数据
    Number status 状态码(200/304)
    String statusText 状态文本(OK)

    只要readyState属相的值由一个值变为另一个值,都会触发一次readystatechange事件。也就是说可以用xhr对象监听readystatechange事件,从而在其回调函数中进行逻辑操作。

    xhr.onreadystatechange = function(){
      if(xhr.readyState == 4){
        if(xhr.status >= 200 && xhr.status <= 300 || xhr.status == 304){
          alert(xhr.responseText)
        }else{
          alert(xhr.status)
        }
      }
    }

    XMLHttpRequest 2级

    FormData为序列化表单以及创建与表单格式相同的数据(用于通过xhr传输)提供了遍历。

    let formdata = new FormData()
    formdata.get(key)
    formdata.getAll(key)
    formdata.append(key,value)
    formdata.set(key,value)
    formdata.has(key)
    formdata.delete(key)
    formdata.entries()
    formdata.keys()
    formdata.values()

    超时设定:xhr对象添加了timeout属性,表示请求在等待多少毫秒之后就终止。还可以监听timeout事件。(前提是请求超时终止)

    xhr.timeout = 1000
    xhr.ontimeout = function (){
     
    }

    overrideMimeType()方法,用于重写xhr响应的MIME类型。比如:服务器返回的MIME类型时text/plain,但是数据中实际包含的是XML。根据MIME类型,即使数据时XML,responseXML属性中仍然是null。通过此方法可以保证响应当做XML而非纯文本处理。

     进度事件

    loadstart:在接收到响应数据的第一个字节时触发。
    progress:在接收响应期间持续不间断触发。
    error:在请求发生错误时触发。
    abort:在因为调用abort()方法而终止连接时触发。
    load:在接收到完整的响应数据时触发。
    loadend:在通信完成或者触发error、abort、或load事件后触发。

    实现一个进度指示器

    xhr添加了progress事件,这个事件会在浏览器接收新数据期间周期性触发。而onprogress事件处理程序会接收到一个event对象,其target属性是xhr对象,但包含着三个额外属性:lengthComputable、position和totalSize。其中lengthComputable是一个表示进度信息是否可用的布尔值,position表示已经接收的字节数,totalSize表示根据Content-Length响应头部确定的预期字节数。

    跨域问题

    同源策略:同源策略/SOP(Same Origin Policy)是一种约定,它是浏览器最核心最基础的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。

    跨域:当协议、域名、端口号有一个或多个不同时,又希望可以访问并获取数据的现象称为跨域访问。

    误区:同源策略限制下,访问不到后台服务器的数据,或访问到后台服务器的数据没有返回
    正确:同源策略限制下,可以访问到后台服务器的数据,后台服务器会正常返回数据,只是被浏览器拦截了。

    实现跨域的方式:写几种常见的方式

    jsonp

    只能发送get请求,不支持post、put、delete
    不安全,很容易受到XSS攻击
    function cbFn(data){
      alert(data.name + data.age)
    }
    
    let script = document.createElement('script')
    script.src = 'http://www.zjy.com?callback=cbFn'
    document.body.appendChild(script)
    
    //请求'http://www.zjy.com?callback=cbFn,后端返回的应该是这样的数据格式"cbFn({name:'zhangsan',age:18})"

    使用CORS跨域:个人理解就是后端解决,也不用前端操心

    跨源资源共享/CORS(Cross-Origin Resource Sharing)
    基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应应该成功还是失败。
    设置哪个源可以访问,也可以设置 固定源,参数为 * 时,允许任何人访问,但是不可以和 cookie 凭证的响应头共同使用
    "Access-Control-Allow-Origin": *
     
    想要获取 ajax 的头信息,需设置响应头
    "Access-Control-Allow-Headers":"key"
     
    处理复杂请求的头
    "Access-Control-Allow-Methods": "PUT"

    允许发送 cookie 凭证的响应头
    "Access-Control-Allow-Credentials": true

    允许前端获取哪个头信息
    "Access-Control-Expose-Headers": "key"

    处理 OPTIONS 预检的存活时间,单位 s
    "Access-Control-Max-Age": 10

    使用postMessage实现跨域

    postMessage是H5的新的API,跨文档消息传送(cross-document messaging),简称为XMD。指的是来自不同域的页面见传递消息。
     
    调用方式
    window.postMessage(message,targetOrigin)
    message:发送的数据
    targetOrigin:发送的窗口的域
    在对应的页面中用message事件接收,事件对象中有data、origin、source三个重要信息。
    data:接收到的数据
    origin:接收到数据源的域(数据来自哪个域)
    source:接收到数据源的窗口对象(数据来自哪个窗口对象)

    使用WebSocket实现跨域:WebSocket没有跨域限制

    怎么使用去看WebSocket就可以了不过多说明了
    或是我上面写的实现WebSocket心跳,基本上也用到几乎所有WebSocket中的API。
    WebSocket的API比较简单,用法也相对简单

    vue框架开发出现的跨域问题:这种方式应该是目前开发应用到最多的地方
    可以在vue-cli脚手架config/index.js里面配置proxyTable,使用proxy代理。
    其实这个配置项可以好好研究一下,一般开发的时候也不会注意到,里面还有哪些配置项,具体查一下用法就可以了

    proxyTable:{
        '/api':{ //根据这个字段去匹配
             target:"http://www.zjy.com", //替换成的地址
             changeOrigin:true, //是否跨域
             pathRewrite:{ //重写路径
                "/api":""
             }
        }
    }    

    还有window.name、location.hash与iframe结合解决跨域问题
  • 相关阅读:
    游标cursor
    SQL: EXISTS
    LeetCode Reverse Integer
    LeetCode Same Tree
    LeetCode Maximum Depth of Binary Tree
    LeetCode 3Sum Closest
    LeetCode Linked List Cycle
    LeetCode Best Time to Buy and Sell Stock II
    LeetCode Balanced Binary Tree
    LeetCode Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/zhenjianyu/p/12965498.html
Copyright © 2011-2022 走看看