Promise介绍
-
什么是Promise?
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个¬对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 -
同步和异步
JavaScript的执行环境是「单线程」。
所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程。
但实际上还有其他线程,如事件触发线程、ajax请求线程等。
这也就引发了同步和异步的问题。- 同步
同步模式,即上述所说的单线程模式,一次只能执行一个任务,函数调用后需等到函数执行结束,返回执行的结果,才能进行下一个任务。如果这个任务执行的时间较长,就会导致「线程阻塞」。
同步模式比较简单,也较容易编写。但问题也显而易见,如果请求的时间较长,而阻塞了后面代码的执行,体验是很不好的。因此对于一些耗时的操作,异步模式则是更好的选择。 - 异步
异步模式,即与同步模式相反,可以一起执行多个任务,函数调用后不会立即返回执行的结果,如果任务A需要等待,可先执行任务B,等到任务A结果返回后再继续回调。
最常见的异步模式就数定时器了,我们来看看以下的例子。
由于定时器是异步的,异步任务会在当前脚本的所有同步任务执行完才会执行。如果同步代码中含有死循环,即将上例的注释去掉,那么这个异步任务就不会执行,因为同步任务阻塞了进程。 - 回调函数
提起异步,就不得不谈谈回调函数了。上例中,setTimeout里的function便是回调函数。可以简单理解为:(执行完)回(来)调(用)的函数。
常见的异步回调即ajax请求。
- 同步
-
为什么要使用Promise?
Promise对象是用于异步操作的。既然我们可以使用异步回调来进行异步操作,为什么还要引入一个Promise新概念,还要花时间学习它呢?不要着急,下面就来谈谈Promise的过人之处。
我们先看看下面的demo,利用Promise改写上面例子的异步回调。
这么一看,并没有什么区别,还比上面的异步回调复杂,得先新建Promise再定义其回调。其实,Promise的真正强大之处在于它的多重链式调用,可以避免层层嵌套回调。如果我们在第一次ajax请求后,还要用它返回的结果再次请求呢?
以上出现了多层回调嵌套,有种晕头转向的感觉。这也就是我们常说的厄运回调金字塔(Pyramid of Doom),编程体验十分不好。而使用Promise,我们就可以利用then进行「链式回调」,将异步操作以同步操作的流程表示出来。
是不是明显清晰很多?孰优孰略也无需多说了吧~下面就让我们真正进入Promise的学习。
4. Promise的基本用法
Promise对象代表一个未完成、但预计将来会完成的操作。
它有以下三种状态:
-
pending:初始值,不是fulfilled,也不是rejected
-
fulfilled:代表操作成功
-
rejected:代表操作失败
Promise有两种状态改变的方式,既可以从pending转变为fulfilled,也可以从pending转变为rejected。一旦状态改变,就「凝固」了,会一直保持这个状态,不会再发生变化。当状态发生变化,promise.then绑定的函数就会被调用。
注意:Promise一旦新建就会「立即执行」,无法取消。这也是它的缺点之一。- 基本用法
下面我们通过一个简单的示例来演示下Promise的使用。- 第一步: 创建Promise实例
类似构建对象,我们使用new来构建一个Promise。Promise接受一个「函数」作为参数,该函数的两个参数分别是resolve和reject。这两个函数就是「回调函数」,由JavaScript引擎提供。
- 第一步: 创建Promise实例
- 基本用法
-
resolve函数的作用:在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
-
reject函数的作用:在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
* 第二步:用then方法指定resolved状态和reject状态的回调函数。
then方法会返回一个Promise。它有两个参数,分别为Promise从pending变为fulfilled和rejected时的回调函数(第二个参数非必选)。这两个函数都接受Promise对象传出的值作为参数。
Promise新建后就会立即执行。而then方法中指定的回调函数,将在当前脚本所有同步任务执行完才会执行。如下例所示。 -
基本API
.then()
语法:Promise.prototype.then(onFulfilled, onRejected)
对promise添加onFulfilled和onRejected回调,并返回的是一个新的Promise实例(不是原来那个Promise实例),且返回值将作为参数传入这个新Promise的resolve函数。因此,我们可以使用链式写法。
.catch
语法:Promise.prototype.catch(onRejected)
该方法是.then(undefined, onRejected)的别名,用于指定发生错误时的回调函数。
注意:promise状态一旦改变就会凝固,不会再改变。因此promise一旦fulfilled了,再抛错,也不会变为rejected,就不会被catch了。
.all()
语法:Promise.all(iterable)
var p = Promise.all([p1, p2, p3]);
Promise.all方法接受一个数组(或具有Iterator接口)作参数,数组中的对象(p1、p2、p3)均为promise实例(如果不是一个promise,该项会被用Promise.resolve转换为一个promise)。它的状态由这三个promise实例决定。
当p1, p2, p3状态都变为fulfilled,p的状态才会变为fulfilled,并将三个promise返回的结果,按参数的顺序(而不是 resolved的顺序)存入数组,传给p的回调函数。
当p1, p2, p3其中之一状态变为rejected,p的状态也会变为rejected,并把第一个被reject的promise的返回值,传给p的回调函数。
.race()
语法:Promise.race(iterable)
var p = Promise.race([p1, p2, p3]);
Promise.race方法同样接受一个数组(或具有Iterator接口)作参数。当p1, p2, p3中有一个实例的状态发生改变(变为fulfilled或rejected),p的状态就跟着改变。并把第一个改变状态的promise的返回值,传给p的回调函数。
在第一个promise对象变为resolve后,并不会取消其他promise对象的执行。
Promise封装了一个异步操作,支持链式调用,将异步的操作以同步的流程表示出来。 语法糖。
Axios介绍和使用
- Axios简介
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据 eval()
- 安装和使用
- 方式一: npm install axios
- 方式二:使用cdn
- 基础使用例子
- 发送get请求
- 发送post请求
- 导入相关的配置发起请求
Axios(config); 或者 axios(url,[config])
- 发送get请求
- 请求方法的别名
- axios.request(config)
- axios.get(url[, config])
- axios.post(url,[,data[, config]])
- 同时发生的请求
提供两个用来处理同时发生多个请求的辅助函数 - axios.all(iterable)
- axios.spread(callback) : 用于展开回调函数的参数
- 创建一个实例
通过实例对象也可以调用诸如 requet, get , post 等方法
- 响应的组成部分
- Axios的配置
- 全局修改axios的默认配置
- 实例默认配置
- 配置优先级
配置项通过一定的规则合并,request config > instance.defaults > 系统默认,优先级高的覆盖优先级低的
- Axios的拦截器
你可以在then和catch之前拦截请求和响应。
如果之后想移除拦截器你可以这么做.
- Vue项目中使用axios
建议执行全局注册,而不是每个组件都单独引入。
import axios from ‘axios’ ;
Vue.prototype.$http = axios ;