ES6 promise

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

特点

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

缺点

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

实例分析

/* 用于描述思维的代码 */
function Promise(executor) {
    // 共有三种状态:pending(准备)、fulfilled(完成)、rejected(拒绝)
    this.PromiseStatus = 'pending';
    // 用于存储返回的数据
    this.PromiseValue;
    // 完成
    var resolve = function(reson) {};
    // 拒绝
    var reject = function(reson) {};
    ...
    // 开始执行承诺
    executor(resolve, reject);
}
Promise.prototype.then = function() {};
Promise.prototype.chain = function() {};
Promise.prototype.catch = function() {};

例:

var http = {
    get: function(url) {
        var promise = new Promise(function(resolve, reject) {
            $.ajax({
                url: url,
                method: 'get',
                success: function(data) {
                    resolve(data);
                },
                error: function(xhr, statusText) {
                    reject(statusText);
                }
            });
        });
        return promise;
    }
};
http.get('solve.php').then(function(data) {
    return data;
}, function(err) {
    return Promise.reject('Sorry, file not Found.');
}).then(function(data) {
    document.write(data);
}, function(err) {
    document.write(err);
});

分析过程
当http调用get()方法时候执行executor(也就是例子里的Promise里的参数函数)。注:实例化Promise的时候就会执行参数里的函数

执行executor内容发出了ajax请求,成功返回,且有返回结果的时候,执行resolve(data),resolve把promise的PromiseStatus的值设为fulfilled, PromiseValue的值设为data;同样reject也是类似,只是把PromiseStatus的值设为rejected

当PromiseStatus的值被改来不为pending的时候就会出发promise的then函数 ,then方法的参数接受两个方法参数,分别对应fulfilled和rejected的回调,触发条件是Promise.PromiseStatus的值。 注:这里的then也是个异步

当调用Promise的then方法的时候,例如 promise.then( fun1(data){ … return result }, fun2(data){… return result}) 返回的依旧是一个Promise对象,此时新的Promise对象的PromiseStatus的值就是fun1/fun2函数里返回的值 。所以依旧可以再调用then方法,形成链式调用

Promise原型上三个重要的方法

Promise.prototype.then   、Promise.prototype.catch  、Promise.prototype.finnally
Promise.prototype.catch方法是.then(null,rejection)的别名,用于制定发生错误时候的回调函数
Promise.prototype.finnally则是无论状态如何都会调用的方法

Promise.all()

const p = Promise.all([p1, p2, p3]);
// Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,
//p的状态:fulfilled: 当p1、p2、p3的状态全为fulfilled,所有返回值组成一个数组作为p的值
//rejected: 当p1、p2、p3其中一个为rejected,首先状态为rejected的值将会传给p

Promise.race()

const p = Promise.race([p1, p2, p3]);
Promise.race()也是将多个Promise实例,包装成一个新的Promise实例
p的状态,fulfilled: 当p1、p2、p3的状态有一个为fulfilled,首先状态为fulfilled的值将会传给p
rejected: p1、p2、p3的状态全为rejected,所有返回值组成一个数组作为p的值

Promise.resolve()、Promise.reject()

//Promise.resolve(): 返回Promise对象,
//参数: 1、Promise对象,直接返回该Promise对象。
//     2、参数是一个thenable对象(),将会将该对象变成Promise对象,并立即执行thenable对                                                       象的then()。
//     3、不是Promise和thenable对象,或者不是对象,直接放回一个状态为fulfilled的Promise                                                            对象,且将参数作为值传入。
//    4、不带参数,直接放回一个状态为fulfilled的Promise对象。
//Promise.reject(): 返回状态为rejected的Promise对象,
//                 参数: 直接作为返回Promise对象的值

Promise.try
问题引入:

下面的代码存在一个问题,因为then是异步的,所以要到本轮事件循环的末尾执行,如果Promise里包裹的是异步请求,这个没毛病,但如果不是(有些时候我们都不知道是不是异步请求),同步就被异步执行了

const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now

解决方法1,利用async

const f = () => console.log('now');
(async () => f())();
console.log('next');
// now
// next

解决方法2,用立即执行的匿名函数

const f = () => console.log('now');
(
  () => new Promise(
    resolve => resolve(f())
  )
)();
console.log('next');
// now
// next
   2、当抛出一些同步错误,比如(数据库连接错误)就只能用try,catch处理了,如下
try {
  database.users.get({id: userId})   //dtabase.user.get()返回一个Promise对象
  .then(...)
  .catch(...)
} catch (e) {
  // ...
}

上面个两种情况发生时候,我们都可以用Promise.try(),很优雅的解决问题

Promise.try(database.users.get({id: userId}))
  .then(...)
  .catch(...)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值