• Promise


    Promises模型

    Promises是一个异步编程模型,它通过一组API来规范化异步操作。

    Promises模型的基本概念可以总结为:

    1. Promises 作为结果或错误的占位符
    2. 提供了一种在结果完成或错误发生时的通知方式

    对于Promises模型而言,已经提出了多个实现的草案:如Promises/A,Promises/B等等。还有一些可以参看:http://wiki.commonjs.org/wiki/Promises

    Promises/A

    简称“thenable",事实上,每一个Promise对象都有一个方法:then(fulfilledHandler,errorHandler,progressHandler)。因为Promise对象有三个状态:unfulfilled,fulfilled,failed,也就是未完成的,完成的和失败的。当一个Promise对象由unfulfilled状态变为fulfilled状态后,fulfilledHandler函数会被调用。当进度事件发生时,progressHandler会被调用。通常progress事件可以省略。

    jQuery Deferred对象

    Deferred概念从jQuery的1.5版本开始引用,它是Promises/A标准的一种衍生实现。通过调用jQuery.Deferred()方法,可以创建Deferred对象,它是一个可以链式操作的对象,并能够注册多个回调函数到回调队列,在异步操作成功或者失败时转达消息。

    defer在英文中的意思是延迟,因此我们可以理解为Deferred对象为延迟执行的对象。

    Deferred对象有三个动作:resolve(解决)、reject(拒绝)和notify(通知)

    Deferred对象可以通过一些方法主动调用这三个动作:deferred.resolve()、deferred.reject()和deferred.notify()。当然,还有一些回调对应不同的状态,如:

    • resolved时调用deferred.done()回调;
    • rejected时调用deferred.fail()回调;
    • resolved或者rejected时调用deferred.always()回调;
    • inProgress时调用deferred.progress()回调;
    • resolved、rejected或者inProgress时调用then()回调;

    有人可能会问then()和always()有什么区别?其实这两个是相似的,只是then函数有两个参数:resolved时的回调和rejected时的回调,相当于将done()和fail()函数合并了,而always函数只有一个回调函数作为参数,不管是resolved还是rejected时,都会执行这个回调。

     1 jQuery.Deferred = function( func ) {
     2     /* Callback参数
     3     once: 所有回调函数只执行一次
     4     memory: 触发回调后对象可以继续添加函数,添加的函数会马上被触发
     5     unique: 保证相同的回调函数只能添加一次
     6     stopOnFalse: 当回调返回false时停止触发
     7     */
     8         var tuples = [
     9                 // action, add listener, listener list, final state
    10                 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
    11                 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
    12                 [ "notify", "progress", jQuery.Callbacks("memory") ]
    13             ],
    14             state = "pending",
    15             promise = {
    16                 state: function() {
    17                     return state;
    18                 },
    19                 always: function() {
    20                     deferred.done( arguments ).fail( arguments );
    21                     return this;
    22                 },
    23                 then: function( /* fnDone, fnFail, fnProgress */ ) {
    24                     var fns = arguments;
    25                     return jQuery.Deferred(function( newDefer ) {
    26                         jQuery.each( tuples, function( i, tuple ) {
    27                             var action = tuple[ 0 ],
    28                                 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
    29                             // deferred[ done | fail | progress ] for forwarding actions to newDefer
    30                             deferred[ tuple[1] ](function() {
    31                                 var returned = fn && fn.apply( this, arguments );
    32                                 if ( returned && jQuery.isFunction( returned.promise ) ) {
    33                                     returned.promise()
    34                                         .done( newDefer.resolve )
    35                                         .fail( newDefer.reject )
    36                                         .progress( newDefer.notify );
    37                                 } else {
    38                                     newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
    39                                 }
    40                             });
    41                         });
    42                         fns = null;
    43                     }).promise();
    44                 },
    45                 // Get a promise for this deferred
    46                 // If obj is provided, the promise aspect is added to the object
    47                 promise: function( obj ) {
    48                     return obj != null ? jQuery.extend( obj, promise ) : promise;
    49                 }
    50             },
    51             deferred = {};
    52 
    53         // Keep pipe for back-compat
    54         promise.pipe = promise.then;
    55 
    56         // Add list-specific methods
    57         jQuery.each( tuples, function( i, tuple ) {
    58             var list = tuple[ 2 ],
    59                 stateString = tuple[ 3 ];
    60 
    61             // promise[ done | fail | progress ] = list.add
    62             promise[ tuple[1] ] = list.add;
    63 
    64             // Handle state
    65             if ( stateString ) {
    66                 list.add(function() {
    67                     // state = [ resolved | rejected ]
    68                     state = stateString;
    69 
    70                 // [ reject_list | resolve_list ].disable; progress_list.lock
    71                 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
    72             }
    73 
    74             // deferred[ resolve | reject | notify ]
    75             deferred[ tuple[0] ] = function() {
    76                 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
    77                 return this;
    78             };
    79             deferred[ tuple[0] + "With" ] = list.fireWith;
    80         });
    81 
    82         // Make the deferred a promise
    83         promise.promise( deferred );
    84 
    85         // Call given func if any
    86         if ( func ) {
    87             func.call( deferred, deferred );
    88         }
    89 
    90         // All done!
    91         return deferred;
    92     }
    jQuery Deferred

    此外,还有两个方法:

    • deferred.promise():在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。
    • deferred.when(): 可以传入多个deferred对象,并为他们指定同一个回调(其实就是deferred队列管理的功能)。

    关于Deferred对象的更多细节请看API: http://api.jquery.com/category/deferred-object/

    Node.js和Promises

    我们知道,node.js是异步编程的,对于新手而言,异步编程导致的一个常见的问题就是异步嵌套过深。解决的方法有若干个,一个是使用Event,也就是在合适的时间emit某一个事件,那么代码就变为了一行一行的on('xxx',callback);另一个解决方法就是使用异步管理的库,如async等;还有就是我们现在讨论的Promises模型。

    Nodejs中比较流行的Promises库就是Q Library。它的项目主页是:https://github.com/kriskowal/q

    • Q.fcall():创建Promise对象
    • Q.defer():生成defer对象,可以通过调用resolve和reject方法等改变对象的状态
    • Q.all():等待一个数组中的所有Promise对象都执行完毕

    一个例子是:

    function get_all_the_things(things) {
        var the_promises = [];
    
        things.forEach(function(thing) {
            var deferred = Q.defer();
            get_a_thing(thing, function(result) {
                deferred.resolve(result);
            });
            the_promises.push(deferred.promise);
        });
    
        return Q.all(the_promises);
    }

    还有其他的功能,由于还不熟悉,就先到这里。

  • 相关阅读:
    cpu capacity、task_util、cpu_util是如何计算的?
    QTI EAS学习之find_energy_efficient_cpu
    Linux内核进程调度overview(1)
    Ondemand和Interactive gonernor工作逻辑简述
    利用init进程监控底层节点的方法架构
    Sched_Boost小结
    SchedTune
    Cpusets学习
    搭建SpringCloud微服务框架:三、读取Nacos的配置信息
    搭建SpringCloud微服务框架:一、结构和各个组件
  • 原文地址:https://www.cnblogs.com/cubika/p/3492003.html
Copyright © 2020-2023  润新知