前端总结·基础篇·JS(四)异步请求及跨域方案
前端总结系列
- 前端总结·基础篇·CSS(一)布局
- 前端总结·基础篇·CSS(二)视觉
- 前端总结·基础篇·CSS(三)补充
- 前端总结·基础篇·JS(一)原型、原型链、构造函数和字符串(String)
- 前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)
- 前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数
- 前端总结·基础篇·JS(四)异步请求及跨域方案
- 前端总结·工具篇·管理(一)常用模块化方案
目录
一、异步请求
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。
参考
- AJAX - MDN
- XMLHttpRequest - MDN
- XHR——XMLHttpRequest对象 - gaojun
- XMLHttpRequest 对象 - W3Scool
- 跨域资源共享 CORS 详解 - 阮一峰
- JavaScript异步编程(1)- ECMAScript 6的Promise对象 -
- fetch使用的常见问题及解决办法 - wonyun
- 你不需要jQuery(三):新AJAX方法fetch() - 唸随爱
- 深入浅出Fetch API 带你入解应用场景及适用问题 - Ludovico Fischer
前端总结·基础篇·JS(四)异步请求及跨域方案的更多相关文章
- 前端总结·基础篇·JS(一)五大数据类型之字符串(String)
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(二)补充 前端总结·基础篇·JS(一)五大数据类型之字符串(String) 目录 这是& ...
- 前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)
目录 这是<前端总结·基础篇·JS>系列的第二篇,主要总结一下JS数组的使用.技巧以及常用方法. 一.数组使用 1.1 定义数组 1.2 使用数组 1.3 类型检测 二.常用技巧 2.1 ...
- 前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- 前端总结·基础篇·JS(一)原型、原型链、构造函数和字符串(String)
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- 一篇搞定vue请求和跨域
vue本身不支持发送AJAX请求,需要使用vue-resource.axios等插件实现 axios是一个基本Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对v ...
- Vue--axios:vue中的ajax异步请求(发送和请求数据)、vue-resource异步请求和跨域
跨域原理: 一.使用axios发送get请求 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 & ...
- 关于Ajax的get与post浅分析,同步请求与异步请求,跨域请求;
Ajax局部异步刷新全称ASynchronous JavaScript And XML.使用Javascript代码获取服务器的数据,Ajax当中有两个请求方法,一个是get方法,一个是post请求方 ...
- 前端总结·基础篇·CSS(一)布局
目录 这是<前端总结·基础篇·CSS>系列的第一篇,主要总结一下布局的基础知识. 一.显示(display) 1.1 盒模型(box-model) 1.2 行内元素(inline) &am ...
- 前端总结·基础篇·CSS(二)视觉
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·CSS(四)兼容 目录 一.动画(animation)(IE ...
随机推荐
- excel表格的特殊需求引发的Java思考
前言: 前些天遇到了这样的一个需求,将下图: 将表格中货号-前面部分一致的行合成一行,并且将第二行,第三行的价格添加到第一行中为价格二,价格三.如图: 接到这样的需求,我的第一感觉是直接手动合并(暗暗 ...
- [css 揭秘]:CSS揭秘 技巧(三):背景定位
我的github地址:https://github.com/FannieGirl/ifannie 源码都在这上面哦! 喜欢的给我一个星吧 背景定位 问题:很多时候,我们想针对容器某个角对背景图片做便宜 ...
- 使用jquery的load方法设计动态加载,并解决被加载页面JavaScript失效问题
一.问题分析 对于后台系统,相比大家都有所印象,知道其中的布局结构,如图: 在这种布局中我们需要将header,sidebar,footer分开,而且对于中间部分的content内容需要动态变化,即根 ...
- php调用API支付接口(使用第三方接口,调用的天工接口。)
首先访问 https://charging.teegon.com/ 注册账号, 找到开发配置 记下client_id和client_secret. 点击 天工开放平台 点击天工收银 点击 S ...
- iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- smarty fetch方法
fetch 取得输出的内容 返回一个模板输出的内容(HTML代码),而不是直接显示出来,需要指定一个合法的模 板资源的类型和路径.你还可以通过 第二个可选参数指定一个缓存号,相关的信息可以查看缓存 ...
- RxSwift 入坑好多天 - 终于有了一点理解
一.前言 江湖上都在说现在就要赶紧学 swift 了,即将是 swift 的天下了.在 api 变化不大的情况下,swift 作为一门新的语言,集众家之所长,普通编码确实比 oc 要好用的多了 老早就 ...
- Flume-ng源码解析之启动流程
今天我们通过阅读Flume-NG的源码来看看Flume的整个启动流程,废话不多说,翠花,上源码!! 1 主类也是启动类 在这里我贴出Application中跟启动有关的方法,其他你们可以自己看源码,毕 ...
- Gradle之恋-任务1
任务作为Gradle的核心功能模块,而且Gradle的任务还可以具有自己的属性和方法,大大扩展了Ant任务的功能.由于任务相关内容比较多,分为两篇来探讨,本篇主要涉及到:任务的定义.任务的属性.任务的 ...
- Debian部署RMI异常:java.rmi.ConnectException: Connection refused to host: 127.0.1.1;
现象:在windows上部署RMI很顺利,但移到debian上部署后,客户端报异常: java.rmi.ConnectException: Connection refused to host: 12 ...