Javascript中的Promise

Posted 清姿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript中的Promise相关的知识,希望对你有一定的参考价值。

Promise定义

Promise是CommonJs的规范之一,包含resolve,reject,done,fail,then等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套。异步在web开发中越来越重要,对于开发人员来说,J非线性执行的编程会让开发者觉得难以掌控,而Promise可以让我们更好地掌控代码的执行流程,jQuery等流行的js库都已经实现了这个对象,现在ES6已经原生实现了Promise。

场景说明:

有时候会遇到这样的情况,需要发两个异步请求,而第二个请求需要用到第一个返回结果的数据:

ajax({
        url: url1,
        success: function(data) {
            ajax({
                url: url2,
                data: data,
                success: function() {
                }
            });
        }
});

稍微整理一下,把后一个调用封装成一个函数,就是酱紫滴:

    function A() {
        ajax({
            url: url1,
            success: function(data) {
                B(data);
            }
        });
    }
    function B(data) {
        ajax({
            url: url2,
            success: function(data) {
                ......
            }
        });
    }

如果异步请求C又需要用到B的结果,又需要一层。如果需要很多层,代码可读性会降低,最后不忍直视了就。所以就有了Promise。有了Promise,代码就是酱紫了:

new Promise(A).done(B);

很清爽很DRY有木有?

ES6已经实现了Promise,不过也可以自己写一个Promise对象:

用两个数组(doneList和failList)来存储成功时的回调函数队列和失败时的回调函数队列。

此对象的方法和属性:

1.state: 当前执行状态,有pending、resolved、rejected3种取值

2.done: 向doneList中添加一个成功回调函数

3.then: 分别向doneList和failList中添加回调函数

4.always: 添加一个无论成功还是失败都会调用的回调函数

5.resolve: 将状态更改为resolved,并触发绑定的所有成功的回调函数

6.reject: 将状态更改为rejected,并触发绑定的所有失败的回调函数

7.when: 参数是多个异步或者延迟函数,返回值是一个Promise兑现,当所有函数都执行成功的时候执行该对象的resolve方法,反之执行该对象的reject方法

具体实现:

var Promise = function() {
    this.doneList = [];
    this.failList = [];
    this.state = ‘pending‘;
};

Promise.prototype = {
    constructor: ‘Promise‘,
    resolve: function() {
        this.state = ‘resolved‘;
        var list = this.doneList;
        for(var i = 0, len = list.length; i < len; i++) {
            list[0].call(this);
            list.shift();
        }
    },
    reject: function() {
        this.state = ‘rejected‘;
        var list = this.failList;
        for(var i = 0, len = list.length; i < len; i++){
            list[0].call(this);
            list.shift();
        }
    },
    done: function(func) {
        if(typeof func === ‘function‘) {
            this.doneList.push(func);
        }
        return this;
    },
    fail: function(func) {
        if(typeof func === ‘function‘) {
            this.failList.push(func);
        }
        return this;
    },
    then: function(doneFn, failFn) {
        this.done(doneFn).fail(failFn);
        return this;
    },
    always: function(fn) {
        this.done(fn).fail(fn);
        return this;
    }
};

这个不支持链式调用,可以再来个支持链式调用的:

var MPromise = function(func){
    this.doneList = [];
    this.state = ‘pending‘;
    func(this.resolve.bind(this));
    this.self = this;
}
MPromise.prototype = {
    resolve: function(){
        var args = arguments[0];

        while(true){
            args = [args];
            this.lastargs = args;

            if( this.doneList.length == 0 ){
                this.state = ‘done‘;
                break;
            }

            args = this.doneList.shift().apply(this, args);

            if( args instanceof MPromise ){
                this.self = args;
                args.doneList = args.doneList.concat(this.doneList.slice(0));
                this.state = ‘done‘;
                this.doneList.length = 0;
                break;                        
            }
        }
    },
    then: function(callback){
        this.doneList.push(callback);
        if( this.state == ‘done‘ ){
            this.state = ‘pending‘;
            this.resolve.apply(this, this.lastargs);
        }
        return this.self;
    }
}

ES6-Promise

ES6提供了原生Promise对象:从语法上说,Promise是一个对象,从中可以获取异步操作的消息。

基本用法:

ES6中的Promise对象是一个构造函数,用来生成Promise实例。

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise对象接收一个函数作为参数,这个函数的两个参数分别是resolve和reject,这两个函数由javascript引擎提供,不用自己部署。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

 

以上是关于Javascript中的Promise的主要内容,如果未能解决你的问题,请参考以下文章

Javascript中的Promise

如何等待 JavaScript/TypeScript 中的 Promise 列表?

在javascript承诺中执行的顺序是什么

无法使用 javascript 中的 Promise 遍历问题数组中的每个项目

前端面试题之手写promise

javaScript-promise