zoukankan      html  css  js  c++  java
  • 全面理解Javascript中Promise

    全面理解Javascript中Promise

    最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 
    比较好的文章,供大家更好地学习js中非常有趣的Promise

    Promise概念

    2015 年 6 月,ECMAScript 6 的正式版 终于发布了。

    ECMAScript 是 JavaScript 语言的国际标准,javascript 是 ECMAScript 的实现。ES6 的目标,是使得 JavaScript 语言可以用来编写大型的复杂的应用程序,成为企业级开发语言。

    –Promise知识JS的一个新对象,为的就是解决js在处理异步的时候产生的多成回调的问题,那么在Promise纳入ES6的规范之前,一些优秀 
    的框架是如何解决这种异步回调的问题的呢? 
    jQuery这个传奇的框架中,已经有方法解决上述问题的方案了,那就是jquery的deferred对象,还没有接触到这个对象的小同学可以想去 
    了解一下,推荐一篇博文jQuery的deferred对象详解。当我了解到JQ中 
    deferred对象的时候,就发现Promise的奥秘其实很简单,跟deferred对象的实现方法有着异曲同工之妙。下面开始从Promise的基础,Promise应用出发带大家了解Promise的美妙

    Promise基础

    –ES6 原生提供了 Promise 对象。

    所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

    Promise 对象有以下两个特点。

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

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

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

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

    var promise = new Promise(function(resolve, reject) {
     if (/* 异步操作成功 */){
     resolve(value);
     } else {
     reject(error);
     }
    });
    
    promise.then(function(value) {
     // success
    }, function(value) {
     // failure
    });

    Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 方法和 reject 方法。

    如果异步操作成功,则用 resolve 方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);

    如果异步操作失败,则用 reject 方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。

    使用Promise组织你的AJAX

    //创建一个Promise实例,获取数据。并把数据传递给处理函数resolve和reject。需要注意的是Promise在声明的时候就执行了。
    var getUserInfo=new Promise(function(resolve,reject){
        $.ajax({
            type:"get",
            url:"index.aspx",
            success:function(data){
                if(data.Status=="1"){
                    resolve(data.ResultJson)//在异步操作成功时调用
                }else{
                    reject(data.ErrMsg);//在异步操作失败时调用
                }
            }
        });
    })
    //另一个ajax Promise对象,
    var getDataList=new Promise(function(resolve,reject){
        $.ajax({
            type:"get",
            url:"index.aspx",
            success:function(data){
                if(data.Status=="1"){
                    resolve(data.ResultJson)//在异步操作成功时调用
                }else{
                    reject(data.ErrMsg);//在异步操作失败时调用
                }
            }
        });
    })
    //Promise的方法then,catch方法
    getUserInfo.then(function(ResultJson){
        //通过拿到的数据渲染页面
    }).catch(function(ErrMsg){
        //获取数据失败时的处理逻辑
    })
    //Promise的all方法,等数组中的所有promise对象都完成执行
    Promise.all([getUserInfo,getDataList]).then(function([ResultJson1,ResultJson2]){
        //这里写等这两个ajax都成功返回数据才执行的业务逻辑
    })

    写一个自己的Promise,揭开Promise的神秘面纱

    –Promise的规范

    1.一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected) 
    2.一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换 
    3.promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致 
    4.then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

    –promise原理分析 
    可以看到promise的规范并不是很多,下面我们一边分析promise一边自己写一个promise的实现。Promise实现的大致思路如下:

      构造函数Promise接受一个函数resolver,可以理解为传入一个异步任务,resolver接受两个参数,一个是成功时的回调,一个是失败时的回调,这两参数和通过then传入的参数是对等的。

    其次是then的实现,由于Promise要求then必须返回一个promise,所以在then调用的时候会新生成一个promise,挂在当前promise的_next上,同一个promise多次调用都只会返回之前生成的_next。

    由于then方法接受的两个参数都是可选的,而且类型也没限制,可以是函数,也可以是一个具体的值,还可以是另一个promise。下面是then的具体实现:

    Promise.prototype.then = function(resolve, reject) {  
        var next = this._next || (this._next = Promise());  
        var status = this.status;  
        var x;  
    
        if('pending' === status) {  
            isFn(resolve) && this._resolves.push(resolve);  
            isFn(reject) && this._rejects.push(reject);  
            return next;  
        }  
    
        if('resolved' === status) {  
            if(!isFn(resolve)) {  
                next.resolve(resolve);  
            } else {  
                try {  
                    x = resolve(this.value);  
                    resolveX(next, x);  
                } catch(e) {  
                    this.reject(e);  
                }  
            }  
            return next;  
        }  
    
        if('rejected' === status) {  
            if(!isFn(reject)) {  
                next.reject(reject);  
            } else {  
                try {  
                    x = reject(this.reason);  
                    resolveX(next, x);  
                } catch(e) {  
                    this.reject(e);  
                }  
            }  
            return next;  
        }  
    };

    参考文献 
    jQuery的deferred对象详解 
    JavaScript进阶之路 
    Javascript 中的神器

  • 相关阅读:
    springboot访问redis序列化问题
    观察者模式在源码中的使用
    抽象工厂模式在源码中的使用
    工厂方法模式在源码中的应用
    策略模式的应用
    springcloud实现限流
    Elasticsearch
    java8新特性(二)StreamApi
    thinkpaidE450 win10 进入bios
    restframe_work2
  • 原文地址:https://www.cnblogs.com/Magiccwl/p/7301271.html
Copyright © 2011-2022 走看看