异步请求及跨域方案

前端总结系列

目录


一、异步请求
    1.1 XHR(XMLHttpRequest)
    1.2 Promise(ES6)
    1.3 Fetch

二、跨域方案
    2.1 JSONP(JavaScript Object Notation with Padding)
    2.2 CORS(Cross-origin resource sharing)

一、异步请求

此文只进行简单的介绍,完整的用例请见我的Github。Github上的用例,对这三种方法的POST和GET请求都进行了封装。

Github演示不支持POST请求,所以会有部分报错。完整测试可以放在本机的localhost下。


a.json
-------------
{
"user":"张三",
"folling":30,
"foller": 20
}

1.1 XHR(XMLHttpRequest)

三行代码实现异步请求

下面是发送XHR请求之后,返回的成功信息。


<script type="text/javascript">
  var xmlhttp = new XMLHttpRequest()  // 创建异步请求
  xmlhttp.open('GET','a.json')  // 使用GET方法获取hello.txt文件
  xmlhttp.send()  // 发送异步请求
</script>

读取异步请求返回的数据

返回的数据存储在xmlhttp.responseText。

怎么返回了这么多内容?请接着往下看。


<script type="text/javascript">
  var xmlhttp = new XMLHttpRequest()
  // 异步请求状态发生改变时会执行这个函数
  xmlhttp.onreadystatechange = function () {
    // 显示返回的内容
    console.log(xmlhttp.responseText)
  }
  xmlhttp.open('GET','hello.txt')
  xmlhttp.send()
</script>

异步请求的状态

现在就好了,我们在使用xmlhttp.responseText之前判断了一下当前ajax的状态。确认完成了,我们才返回值。


<script type="text/javascript">
  var xmlhttp = new XMLHttpRequest()
  xmlhttp.onreadystatechange = function () {
    // status == 200 用来判断当前HTTP请求完成
    if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 ) {
      console.log(xmlhttp.responseText)
    }
  }
  xmlhttp.open('GET','hello.txt')
  xmlhttp.send()
</script>

异步请求一共有五个状态,用来标识异步请求的不同阶段。

  • 0 UNSENT 代理被创建,但尚未调用 open() 方法
  • 1 OPENED open() 方法已经被调用
  • 2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得
  • 3 LOADING 下载中; responseText 属性已经包含部分数据
  • 4 DONE 下载操作已完成

上面返回的五条数据中,一条是XHR请求成功默认返回的。前两条对应的状态1和2,是没有返回内容的,所以为空。后面两条有内容的对应的是3和4。

因此,我们想要数据完全下载完成了再显示返回内容,只需要用if判断一下当前状态是否是4即可。

关于HTTP状态码代表的意义,可以看我之前写过的文章

封装XHR方法


function ajax (method,url,callback) {
  var xmlhttp = new XMLHttpRequest()  // 创建异步请求
  // 异步请求状态发生改变时会执行这个函数
  xmlhttp.onreadystatechange = function () {
    // status == 200 用来判断当前HTTP请求完成
    if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 ) {
      callback(JSON.parse(xmlhttp.responseText))  // 执行回调
    }
  }
  xmlhttp.open(method,url)  // 使用GET方法获取
  xmlhttp.send()  // 发送异步请求
}

调用XHR方法


ajax('GET','a.json',function (res) {
  console.log(res)  // 显示返回的对象
  ajax('GET','b.json',function (res) {
    console.log(res)
    ajax('GET','c.json',function (res) {
      console.log(res)
    })
  })
})

1.2 Promise(ES6)

我们在用Ajax写异步的时候,很容易掉入回调地狱(callback),代码的可读性会大大的下降。Promise可以让代码变得更优雅。

封装基于Promise的XHR


function ajax ( method,url ) {
  // 返回一个Promise对象
  return new Promise(function (resolve) {
    var xmlhttp = new XMLHttpRequest()  // 创建异步请求
    // 异步请求状态发生改变时会执行这个函数
    xmlhttp.onreadystatechange = function () {
      // status == 200 用来判断当前HTTP请求完成
      if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 ) {
        resolve(JSON.parse(xmlhttp.responseText))  // 标记已完成
      }
    }
    xmlhttp.open(method,url)  // 使用GET方法获取
    xmlhttp.send()  // 发送异步请求 
  })
}

调用基于Promise的XHR


var aj = ajax('GET','a.json')
aj.then(function (res) {
  console.log(res)
})

1.3 fetch

fetch是对Promise的一个封装,使用非常方便。

fetch('a.json').then(function (res){
   return res  // 返回Promise
}).then(function (res) {
   return res.json()  // 返回JSON对象
}).then(function (json) {
   console.log(json)  // 显示JSON内容
})

二、跨域方案

CORS方法更好一些,但是需要对服务器有自主权。JSONP则不需要对服务器有自主权,可以通过script、img等标签可以发送GET请求的特点,通过回调函数执行已有的JS函数。在函数内获取返回值。

CORS支持所有HTTP请求,JSONP只支持GET请求。

2.1 JSONP(JavaScript Object Notation with Padding)


用回调跨域
------------------------
<script type="text/javascript" src="http://localhost/async/cors.php?callback=go"></script>

设置好回调函数
------------------------
function go (arr) {
  console.log(arr)  // 显示回调的值 | {a:"1"}
}

script发送的GET请求时,返回的值是一个函数,遂执行回调函数
------------------------
<?php 
$go=$_GET['callback'];  // 获取callback的值
echo $go.'({a:"1"})';  // 输出回调函数
?>

2.2 CORS(Cross-origin resource sharing)

PHP配置CORS


<?php 
header("Access-Control-Allow-Origin:*");  // *号为允许所有域名,推荐修改成需要跨域的域名
?>

配置CORS前

配置CORS后

总结

下一篇总结Vue。

原文地址:https://www.cnblogs.com/libin-1/p/6658649.html