说说Q.js中的promise的历史

转载自:http://segmentfault.com/a/1190000002591145

Promise核心说明

promise的规范,请百度搜索Prommise/A+规范,promise的核心是有个then方法。在相关术语中,promise指的就是有个 then

方法,且该方法能触发特定行为的对象或函数。

起步:用这一种方法理解Promise

回想一下Promise解决的是什么问题?回调。 例如:函数 doMission1() 代表第一件事情,现在,我们想要在这事情完成后,再做下

一件事情 doMisson2(),应该怎么做呢?

先看看我们常见的回调模式。 doMission1() 说:“你要这么做的话,就把doMission2()交给我,我在结束后帮你调用。" 所以会是:

doMission1( doMission2 );

Promise模式又如何呢?你对 doMission1()说:“不行,控制权要在我这里。你应该要改变一下,你先返回一个特别的东西给我,然

后我来这里安排下一件事。” 这个特别的东西就是Promise,这会变成这样:

doMission1().then( doMission2 );

可以看出,Promise将回调模式的主从关系换了一个位置(翻身做主人!), 多个事件的流程关系,就可以这样集中到主干到上(而不是

分散在各个事件函数之内)。

好了,如何做这样一个转换呢? 从最简单的情况来吧,假定 doMission1()的代码是:

 function doMission1(callback){
     var value = 1;
     callback( value );
 }
 

那么,它可以改变一下,变成这样:

 function doMission1(){
     var value = 1,

         self = {
             then: function( callback ){
                 callback( value );
             }
         };

         return self;
 }

这就完成了转换。虽然并不是实际有用的转换,但到这里,其实已经触及了Promise最为重要的实现要点

Promise将返回值转换为带有 then 方法的对象。

进阶: Q的设计路程

从def开始

 var def = function(){
     var pending = [], value,

         self = {
             resolve: function( _value ){
                 value = _value;
                 for( var i = 0, len = pending.length; i < len; i++ ){
                     var callback = pending[ i ];
                     callback( value );
                 }
                 pending = undefined;
             },

             then: function(){
                 if( pending ){
                     pending.push( callback );
                 }else{
                     callback( value );
                 }
             }
         };

     return self;
 };
 

这段源码可以看出,运行 def() 将得到一个对象,该对象包含 resolve 和 then 方法。请回想一下jQuery的Deferred(同样有

resolve 和 then),这两个方法将会是近似的效果。then 会参考 pending 的状态,如果是等待状态则将回调保存(push),

否则立即调用回调。resolve 则将肯定这个Promise,更新值的同时运行完所有保存的回调。例如:

var oneLater = function(){
    var result = def();

    setTimeout( function(){
        result.resolve( 1 );
    },1000);     

    return result;
};

oneLater().then( function(value){
    console.log( value );
} );

为了解决多次调用resolve, 可以给个状态判断,代码修改如下:

 var def = function(){
     var pending = [], value,

         self = {
             resolve: function( _value ){
                 if( pending ){
                     value = _value;
                     for( var i = 0, len = pending.length; i < len; i++ ){
                         var callback = pending[ i ];
                         callback( value );
                     }
                     pending = undefined;
                 }
             },

             then: function(callback){
                 if( pending ){
                     pending.push( callback );
                 }else{
                     callback( value );
                 }
             }
         };

     return self;
 };

分离der和promise

在前面的实现中,def 生成的对象同时拥有 then 方法和 resolve 方法。按照定义,promise 只关心的是 then 方法,至于

触发 promise 改变状态的 resolve,是另一回事。所以,Q 接下来将拥有 then 方法的 promise,和拥有 resolve 的def

分离开来,各自独立使用。这样就好像划清了各自的职责,各自只留一定的权限,这会使代码逻辑更明晰,易于调整。

看desige/q3.js:

var isPromise = function( value ){
    return value && typeof value.then === "function";
};

var def = function(){
    var pending = [], value,

        self = {
            resolve: function( _value ){
                if(( pending ){
                    value = _value;
                    for( var i = 0, len = pending.length; i < len; i++ ){
                        var callback = pending[ i ];
                        callback( value );
                    }
                    pending = undefined;
                }
            },

            promise: {
                then: function(){
                    if( pending ){
                        pending.push( callback );
                    }else{
                        callback( value );
                    }
                }
            }
        };

        return self.promise;
};

实现promise级联

接下来会是相当重要的一步。到前面的q3为止,所实现的 promise 都是不能级联的。但你所熟知的promise应该支持这样的语法:

promise.then( step1 ).then( step2 );

以上过程可以理解为,promise 将可以创造新的 promise,且取自旧的 promise 的值(前面代码中的 value )。要实现 then

的级联,需要做到一些事情:

1,then 方法必须返回 promise;

2,这个返回的 promise 必须用传递给 then 方法的回调运行后的返回结果,来设置自己的值;

3,传递给 then 方法的回调,必须返回一个 promise 或值;

design/q4.js 中,为了实现这一点,新增了一个工具函数 ref:

var ref = function( value ){
    if( value && typeof value.then === "function" ){
        return value;
    }

    return {
        then: function( callback ){
            var _value = callback( value );
            return ref( _value );
        }
    };
};

如果这个 ref 函数入参 value 是非 promise 对象的话,那么,就会把 value 传递给下一个回调函数,包装成 promise 对象。

ref("step1").then(function(value){
    console.log(value); // "step1"
    return 15;
}).then(function(value){
    console.log(value); // 15
});

你可以看到value是怎样传递的,promise 的级联需要做到的也是如此。

var thenable = function( value ){
    if( value && typeof value.then === "function" ){
        return value;
    }

    return {
        then: function( callback ){
            var _value = callback( value );
            return thenable( _value );
        }
    };
};

var defer = function(){
    var pending = [], value,

        self = {
            resolve: function( _value ){
                if( pending ){
                    //values wrapped in a promise
                    value = thenable( _value );

                    for( i = 0, len = pending.length; i < len; i++ ){
                        var callback = pending[ i ];
                        value.then( callback ); // the called instead.
                    }
                    pending = undefined;
                }
            },

            promise: {
                then: function( _callback ){
                    var result = defer();

                    var callback = function( value ){
                        var _value = _callback( value );
                        result.resolve( _value );
                    };

                    if( pending ){
                        pending.push( callback );
                    }else{
                        value.then( callback );
                    }

                    return result.promise;
                }
            }
        };

        return self;
};

1,每次 then 都会生成新的 promise 对象;

2, 传入的 _callback 都会包装成 callback 函数,新生成的 defer 对象里放置的 resolve 方法,这样是在旧的defer对象resolve时,

通过defer的promise挂接着的callback函数,就可以让新的defer对象继续resolve下去;

下面是测试代码:

var deffered = defer();

deffered.promise.then(function( value ){
        console.log( value );
        return 2;
}).then(function( value ){
    console.log( value );
});

setTimeout( function(){
    deffered.resolve( 1 );
}, 1000);

加入错误处理

promise的 then 方法应该可以包含两个参数,分别是肯定和否定状态的处理函数(onFulfilled 与 onRejected)。前面

我们实现的 promise 还只能转变为肯定状态,所以,接下来应该加入否定状态部分。

请注意,promise的 then 方法的两个参数,都是可选参数。design/q6.js 加入了工具函数 reject 来帮助实现 promise

的否定状态。

var reject = function( reason ){
        return {
            then: function( callback, errback ){
                return ref( errback( reason ) );
            }
        };
};

接下来,再看看design/q6.js的其余部分是:

var defer = function(){
    var pending = [], value,

        self = {
            resolve: function( _value ){
                if( pending ){
                    value = ref( _value );
                    for( var i = 0, len = pending.length; i < len; i++ ){
                        value.then.apply( value, pending[i] );
                    }
                    pending = undefined;
                }
            },

            promise: {
                then: function( _callback, _errback ){
                    var result = defer();

                    _callback = _callback || functioin( value ){
                        return value;
                    };

                    _errback = _errback || function( reason ){
                        return reject( reason );
                    };

                    var callback = function( value ){
                        result.resolve( _callback( value ) );
                    };

                    var errback = function( value ){
                        result.resolve( _callback( value ) );
                    };

                    if( pending ){
                        pending.push([ callback, errback ]);
                    }else{
                        value.then( callback, errback );
                    }

                    return result.promise;
                }
            }
        };

        return self;
};
时间: 2024-10-11 13:15:41

说说Q.js中的promise的历史的相关文章

js中的promise

转载自: http://www.cnblogs.com/1000/p/getting-started-with-promises.html JavaScript有很多槽点,嵌套回调怕是千夫所指. 很久之前,我一直使用async来处理JavaScript异步编程中的嵌套回调问题.当然我也大概的了解过一些其它旨在解决这些问题的类库,诸如EventProxy.Jscex.StepJS.thenjs. 当我第一次看到Promises规范的时候,我根本无法理解它所带来的好处.譬如每个初次学习Promise

js中的promise使用

1 // 0.5秒后返回input*input的计算结果: 2 function multiply(input) { 3 return new Promise(function (resolve, reject) { 4 log('calculating ' + input + ' x ' + input + '...'); 5 setTimeout(resolve, 500, input * input); 6 }); 7 } 8 9 // 0.5秒后返回input+input的计算结果: 1

js中的Promise简单总结(ES6)

例如: 使用回调函数的写法: 使用Promise对象之后的写法: Promise的作用:把回调函数写法分离出来,在异步操作执行完后,用链式调用的方法执行回调函数,对于多层回调来说,非常的方便. 再看如下例子: 此时控制台会输出 'aa'  这个结果 此时控制台还是只有 'aa'  这个结果 此时控制台就会有  'aa'  和  'bb'   这两个结果. 也就是说把回到函数写在 then里面,进行链式调用,分离开来.代码看起来更加清晰. 未完,待总结. 原文地址:http://blog.51ct

大话JS神器之Promise

前段时间的工作中,由于项目要在前端实现存储,于是便使用了websql,而websql的API涉及到了很多的异步问题,如果采取回调函数的方式处理,代码不够优雅,而且不利于理解,于是便找到了Promise,使用之后有一些自己的理解和心得,跟大家在本文中一起分享一下. Promise为何物? Promise中文释义为"誓言"."承诺"之意,根据其音译,那就是"普罗米修斯",这货很强大啊,在希腊神话中,是最具智慧的神明之一,最早的泰坦巨神后代,名字有&q

Angular JS中 Promise用法

一.Promise形象讲解A promise不是angular首创的,作为一种编程模式,它出现在1976年,比js还要古老得多.promise全称是 Futures and promises. 而在javascript世界中,一个广泛流行的库叫做Q 地址是https://github.com/kriskowal/q 而angular中的$q就是从它引入的.promise解决的是异步编程的问题,对于生活在同步编程世界中的程序员来说,它可能比较难于理解,这也构成了angular入门门槛之一,以下将用

$q 实例分析 Angular 中的 Promise

相信有一些开发经验的朋友就应该知道,对于JavaScript而言,promise十分重要,在开发中总能用到.因此掌握好它是一件必须做的事情. 我之前写过一篇文章,工作总结:jQuery高级应用之Deferred对象,介绍jquery中的promise,因此关于promise的基础介绍就不再详细讲解,这篇文章会重点关注angular中promise的实现. 我们首先有一个简单的html标签,下面的例子都会基于这个标签来书写 <div ng-app="app" ng-controll

promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的通知机制. 异步:当事情处理完成后被请求者会发信息通知请求者该事情处理完成.在这期间被请求者可以选择是继续等待命令请求完成还是去做其他事等待被请求者返回. 同步:当事情处理完成后被请求者不会告知请求者,等到请求者发来询问是才会告知 阻塞:非阻塞 指的是请求者 阻塞:针对请求者来说的,委托其他人处理一

js中回调函数,promise 以及 async/await 的对比用法 对比!!!

在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (fn) { var app = getApp() wx.login({ success: res => { let code = res.code; wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) {

promise核心技术 2.两种回调函数 js中error的处理

抽空详细学习一下什么是回调函数(一个回调函数,也被称为高阶函数) 1.什么样的函数是回调函数 自己定义的(sittimeout不是自己定义的) 没有调用 自己执行 1.同步回调与异步回调函数 同步回调函数 const arr = [1, 2, 3] arr.forEach(item => { console.log(item) }) //同步回调,任务启动后(等待完成),直接执行回调函数,再往下执行 console.log("later") 异步回调函数 setTimeout((