功能:
Promise对象用于提供一种在ES6环境下的异步编程解决方案。
要点
状态转换——Promise对象具有三种状态:Pending(进行中)、Fufilled(已成功)以及Rejected(已失败)。
(1)状态转变的过程完全由异步操作的结果决定;
(2)状态转变的过程是一次性的,且不可逆。
基本用法:
1.创建实例。
let promise = new Promise(function(resolve,reject) {
if(/*异步操作成功*/) {
resolve(/*参数1*/);
}
else {
reject(/*参数2*/);
}
});
Promise类对象的构造函数接受一个函数作为其参数,该函数包含两个传参:
(1)resolve:将Promise对象的状态从“未完成”(Pending)变为“完成”(Fufilled),并将操作结果(由开发人员自定义)传递出去。该函数在程序设计人员认为操作成功时调用。
(2)reject:将Promise对象的状态从“未完成”(Pending)变为“失败”(Rejected),并将操作结果(由开发人员自定义)传递出去。该函数在程序设计人员认为操作失败时调用。
2.回调函数
Promise实例生成后,可通过then方法分别指定在Fufilled状态和Rejected状态下的回调函数。回调函数在Promise完成状态转变后执行。
promise.then(function(value) {
//操作成功状态下的回调函数
}, function(error) {
//操作失败状态下的回调函数
})
通过value参数和error参数,可以获取由resolve方法以及reject方法所传出的操作结果。
用法示例
以下代码为Promise的基本用法,在Promise构造函数所接受的传函当中,直接打印信息“inter Promise”,而后调用resolve()函数表明操作成功。
通过其实例promise下的then方法定义回调函数,在回调函数中直接访问其实例以获取操作的执行结果
let promise = new Promise(function(resolve,reject) {
console.log('inter Promise');
resolve('succeed!');
});
promise.then(function() {
console.log('Resolved.');
console.log(promise)//可通过调用Promise实例对象获取执行的结果
})
console.log('Hi!');
执行结果
关于异步
异步的概念
在明确Promise的异步作用之前,先讨论一下同步和异步的概念。由于网上关于同步/异步概念的解读比较杂,解读的角度也有所不同,碍于作者水平有限,所以本文不会对同步/异步的定义下绝对的论断,仅对看到的观点做出简要归纳,能够帮助读者理解Promise的作用即可,如果大家对同步/异步的概念有更好的解释,欢迎留言讨论。
目前对同步/异步的解释主要从以下两个角度进行:(1)多任务之间的关系;(2)单任务执行进度相对于时间线的特点。
从多任务之间关系的角度看——同步执行是指各个任务的执行进度遵循严格的时间先后顺序,即后一项任务的准备必须以前一项任务的完成作为前提条件;相对于同步,异步执行是指各个任务的执行进度不再遵顼严格的执行顺序的要求,从时间上来看(宏观上)允许发生重叠。
看到这里,读者们很容易陷入以下两个误区:
(1)误区一:各个任务之间的关联性。当提到异步多任务时,人们很容易直接理解为各个任务之间彼此独立,执行进度毫不相干。笔者认为这种理解过于极端,如果在时间或进度上各个任务之间毫无关联可言,处于完全而绝对的平行状态,那么再讨论这些任务之间的关系将没有任何意义。因此,笔者认为:异步只是意味着脱离了对先后执行顺序或进度的限制,在一定程度上允许发生平行,而任务之间的进度制约关系依然存在,在某个时刻,一项任务的执行进度依然会对其他任务的进度产生影响。
(2)误区二:与并发、并行之间的关系。很多人会将异步与并发或并行的概念直接画等号,的确,很多资料上会将这两种概念放在一起使用(比如异步并发线程),久而久之就会使人们产生概念混淆。但通过笔者查阅的资料来看,二者在概念上的区别还是很明确的:
1)并发是指在单处理器的条件下,各个任务交替执行,但由于交替的时间较短,因此从宏观上来,各个任务似乎是在“同时”进行。各个任务占用的是同一块资源。
2)并行是指在多处理器的条件下,各个任务在真正意义上同时执行。各个任务占用的资源完全独立,且从时间上(微观)看,各个任务是同时进行的,进度互不相干。
由上述描述可以看出,并发/并行的概念主要用于描述在不同的资源条件下,对多任务需求的实现方式。这里强调资源,因此并发/并行的概念常用于对底层业务(与硬件直接关联)的描述。而异步则着重于任务之间的关系本身,并发/并行通过提供一种资源的使用方式从而实现任务之间关系的转变,也就是说,并发/并行是手段,异步则是目的与归宿。
从单任务执行进度相对于时间的关系角度来看——同步是指该任务的执行过程(或进度)在时间上表现出连续的特点;异步则是指任务的进度在时间上表现出不连续的特点,其可能在某个时间点中止,等到某项其他工作完成后在另一个时间点恢复执行。
从单任务的角度看,Promise对象正是通过回调函数机制将任务从连续的时间线上分解,与其他任务之间发生“交替“(或者从宏观时间的角度讲,发生重叠),进而达到异步。
从微观时间的角度看,Promise构造函数所接受的的传递函数与Promise定义之后的操作,二者之间的关系还是同步的。例子如下:
let myprom = new Promise(function(resolve,reject) {
for(let i=0; i<=5; i++) {
console.log(i);
}
resolve()
})
console.log('7')
myprom.then(function(value){
console.log('6')
})
通过Promise对象将原本连续执行的任务分成两部分:(1)一部分业务(通过for循环体打印数字1~5)放置于构造函数内在定义Promise对象时立即执行;另一部分业务(打印数字6)放置于回调函数中,当所有同步任务(打印数字7)完成后再执行。结果如下:
从微观时间的角度看,Promise对象所包含的业务(打印数字1到5以及回调函数内打印数字6)与打印数字7的业务在时间上是先后执行的,但由于切换时间短,所以从宏观时间的角度看,两项业务是“同时”执行的,由此达到了异步的效果。