ES6中的Promise详解

作者:日期:2017-11-24 14:16:52 点击:146

 

Promise诞生的背景

一谈到JavaScript的异步处理,大家肯定会立刻想到回调函数和事件。但是事件的特点是,如果你错过了它,再去监听,是得不到结果的,而回调存在以下问题:

回调函数嵌套,导致代码不够直观,就是常说的 Callback Hell。 
如果几个异步操作之间并没有前后顺序之分(例如不需要前一个请求的结果作为后一个请求的参数)时,同样需要等待上一个操作完成再实行下一个操作。 
Promise是把类似的异步处理对象和处理规则进行规范化,并按照采用统一的接口来编写,而采取规定方法之外的写法都会出错,promise的功能是可以将复杂的异步处理轻松地进行模式化,Promise最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了.一个 Promise 对象可以理解为一次将要执行的异步操作。

什么是Promise

用白话版本来解释就是把你的异步操作用Promise对象包装一下,这样就规范化了异步的处理流程,然后通过 then 和 catch 来分别注册成功回调函数和失败回调函数。

创建Promise对象,Promise新建后就会立即执行

Promise新建后就会立即执行。resolve函数的参数一般都是异步执行成功后的结果,也可能是另一个Promise实例(即是另一个异步操作),reject函数的参数通常是Error对象的实例。

var promise = new Promise(function(resolve, reject) {
    // 异步处理
    // 处理结束后、 resolve(成功要返回的值) / reject(失败要返回的值)
});

new Promise的快捷方式

Promise.resolve(value);
Promise.reject(error)

thenable

thenable指的是一个具有 .then 方法的对象。Promise.resolve 方法另一个作用就是将 thenable 对象转换为promise对象。即使一个对象具有 .then 方法,也不一定就能作为ES6 Promises对象使用,转换是有条件的。

then 和 catch、resolve和reject

promise对象,注册这个promise对象执行成功时和失败时相应的回调函数.这两个函数都接受Promise对象传出的值作为参数。Promise实例new成以后,用then方法分别指定Resolved状态和Reject状态的回调函数

resolve函数的参数除了正常的值以外,还可能是另一个Promise实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作

var p1 = new Promise(function (resolve, reject) {
});
var p2 = new Promise(function (resolve, reject) {
  resolve(p1);
})

then 中指定的方法调用是异步进行的

每次调用then都会返回一个新创建的promise对象

promise chain传参数使用return

Promise对象名().then(function (value) {
    console.log(value);  
}).catch(function (error) {
    console.log(error);
});

Promise.all 和 Promise.race

Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法。

Promise.race 接收一个promise对象数组为参数,只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。

Promise.props

处理一个 promise 的 map 集合。只要有一个失败,所有的执行都结束。

Promise.props({
 pictures: getPictures(),
 comments: getComments(),
 tweets: getTweets()
}).then(function(result) {
 console.log(result.tweets, result.pictures, result.comments);
});

Promise缺点

1.无法取消Promise,一旦新建它就会立即执行,无法中途取消 
2.如果不设置回调函数,Promise内部抛出的错误,不会反应到外部 
3.当一个Promise对象处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

原生实现Promise

我们要满足状态只能三种状态:PENDING,FULFILLED,REJECTED三种状态,
且状态只能由PENDING=>FULFILLED,或者PENDING=>REJECTED

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

value状态为执行成功事件的入参,deferreds保存着状态改变之后的需要处理的函数以及promise子节点,
构造函数里面应该包含这三个属性的初始化

function Promise(callback) {
    this.status = PENDING;
    this.value = null;
    this.defferd = [];
        setTimeout(
          callback.bind(this, this.resolve.bind(this),this.reject.bind(this)),
        0);
}

Promise.prototype = {
        constructor: Promise,
        //触发改变promise状态到FULFILLED
        resolve: function (result) {
                    this.status = FULFILLED;
                    this.value = result;
                    this.done();
        },
        //触发改变promise状态到REJECTED
        reject: function (error) {
                    this.status = REJECTED;
                    this.value = error;
        },
        //处理defferd
        handle: function (fn) {
                    if (!fn) {
                        return;
                    }
                    var value = this.value;
                    var t = this.status;
                    var p;
                    if (t == PENDING) {
                         this.defferd.push(fn);
                    } else {
                        if (t == FULFILLED && typeof fn.onfulfiled == 'function') {
                            p = fn.onfulfiled(value);
                        }
                        if (t == REJECTED && typeof fn.onrejected == 'function') {
                            p = fn.onrejected(value);
                        }
                    var promise = fn.promise;
                    if (promise) {
                        if (p && p.constructor == Promise) {
                            p.defferd = promise.defferd;
                        } else {
                            p = this;
                            p.defferd = promise.defferd;
                            this.done();
                        }
                    }
                    }
       },
       //触发promise defferd里面需要执行的函数
       done: function () {
                    var status = this.status;
                    if (status == PENDING) {
                        return;
                    }
                    var defferd = this.defferd;
                    for (var i = 0; i < defferd.length; i++) {
                        this.handle(defferd[i]);
                    }
        },
        //储存then函数里面的事件返回promise对象,defferd函数当前promise对象里面      
        then: function (success, fail) {
                   var o = {
                        onfulfiled: success,
                        onrejected: fail
                    };
                    var status = this.status;
                    o.promise = new this.constructor(function () {

                    });
                    if (status == PENDING) {
                        this.defferd.push(o);
                    } else if (status == FULFILLED || status == REJECTED) {
                        this.handle(o);
                    }
                    return o.promise;
        }
};

上一篇: javascript this关键字常见面试题

下一篇: ES6解构赋值详解