JavaScript-ES6(3)之Promise

228 阅读3分钟

什么是Promise?

Promise是异步编程的一种解决方案。 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

ES6异步处理的通用模型

ES官方参考了大量的异步场景,总结出了一套异步通用的模型,这套模型可以覆盖几乎所有的异步场景

在ES6中将某一件事情可以发生异步操作的时候,分成了两个阶段unsettledsettled

unsettled:未决阶段,表示的是事情还在进行前期处理,还没有结果,是进行中的状态。
settled:已决阶段,事情已经有了一个结果,不管成功失败,结果已经无法逆转。

事情总是从未决阶段(unsettled)逐步发展到已决阶段(settled)。并且,未决阶段拥有控制何时通向已决阶段的能力。

ES6将事情划分为三种状态:pending(进行中), resolved(已成功), rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。

  1. pending:挂起,处于未决阶段,则表示这件事情还在挂起(最终结果还没出来)
  2. resolved:已处理,已决阶段的一种状态,表示整件事情已经出现结果,并是一个可以按照正常逻辑进行下去的结果
  3. rejected:已拒绝,已决阶段的一种状态,表示整件事情已经出现结果,并是一个无法按照正常逻辑进行下去的结果,通常用于表示有一个错误

未决阶段有权利决定事情走向,因此,未决阶段可以决定事情最终的状态
pending状态 ——> resolved状态: 把事情变为resolved状态的过程叫做:resolve,推向该状态时,可能会传递一些数据
pending状态 ——> rejected状态: 我们将把事情变为rejected状态的过程叫做:reject,推向该状态时,同样可能会传递一些数据,通常为错误信息

当事情达到已决阶段后,通常需要进行后续处理,不同的已决状态,决定了不同的后续处理

resolved状态:这是一个正常的已决状态,后续处理表示为thenable
rejected状态:这是一个非正常的已决状态,后续处理表示为catchable

为了简单理解,下面我绘制了一个简易流程图,仅供参考

promise的基本使用

const pro = new Promise(function(resolve,reject){

})

未决阶段的处理 通过调用resolve函数将Promise推向已已决阶段的resolved状态
通过调用reject函数将Promise推向已决阶段的rejected状态
resolve和reject均可以传递最多一个参数,表示推向状态的数据

例如:

var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
        }, 2000);
    });
p.then(
    function(data){
        console.log('resolved');
        console.log(data);
    }, 
    function(reason, data){
        console.log('rejected');
        console.log(reason);
    }
);

如上例子,随机一个数,如若小于五输出,大于五错误。

注意:

  1. 未决阶段的处理函数是同步的,会立即执行
  2. thenable和catchable函数是异步的,就算是立即执行,也会加入到事件队列中等待执行,并且,加入的队列是微队列
  3. pro.then可以只添加thenable函数,pro.catch可以单独添加catchable函数
  4. 在未决阶段的处理函数中,如果发生未捕获的错误,会将状态推向rejected,并会被catchable捕获
  5. 一旦状态推向了已决阶段,无法再对状态做任何更改
  6. Promise并没有消除回调,只是让回调变的可控