es6的promise笔记

说明:看了promise的自己一笔记,本文档主要是记录一些遇到的难点,自己查阅资料理解的过程

参考文档

1、阮一峰es6入门

2、姜方鑫 对promise的理解

一、Promise 的含义(摘自阮一峰ES6ru)

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

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

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

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

如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。

一、基本实例分析

promise的大致结构如下(具体的解释去看姜方鑫 对promise的理解,前面附又链接,是个很好的解释)

/* 用于描述思维的代码 */
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);
});

          基础内容就不在这里说了,大家可以去看阮一峰老师的es6入门,前面附有链接,我这里记录几个注意的地方,结合上面给出的promise的结构(大致)和代码例子我们理一下整个过程。

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

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

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

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

    第4点附加知识:

        1)、当fun1和fun2的返执行没有报错和发生异常的时候,返回的Promise对象的的PromiseStatus=fulfilled,所以触发     下 个then的fulfilled的回调,如果要触发rejected的回调,可以在 fun2 里返回 Promise一个Promise对象,并reject();

        2)、当resolve(data)和reject(data),当参数data是Promise对象时候,该参数Promise对象将接管剩下的由then构造的回调链,fulfilled回调和rejected回调的 return 一个Promise对象也一样

二、补充

1、Promise原型上有三个重要方法

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

2、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

3、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的值

4、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对象的值

5、Promise.try

问题引入:

      1、下面的代码存在一个问题,因为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(...)








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值