Promise规范

来源:互联网 发布:node 模块化开发 编辑:程序博客网 时间:2024/05/17 04:36

Promise的出现就是为了解决冗长的callback造成的不便如:

 loadImg('a.jpg', function() {     loadImg('b.jpg', function() {         loadImg('c.jpg', function() {             console.log('all done!');         });     }); });

这样的代码不方便调试和观看 而且多了之后会越来越向右边推挤


Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
字面上可以理解为“承诺”,就是说A调用B,B返回一个“承诺”给A,然后A就可以在写计划的时候这么写:当B返回结果给我的时候,A执行方案S1,反之如果B因为什么原因没有给到A想要的结果,那么A执行应急方案S2,这样一来,所有的潜在风险都在A的可控范围之内了。

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

promise也是CommonJS规范的一部分

最简单的Promise例子

function run(arg1, callback){            //....            callback || callback();        }        run(arg1, function(){            run(arg2, function(){                run(arg3, function(){                    //.....一直嵌套下去                });            });        });

这是传统的方法

使用Promise
function run(arg){            return new Promise(function(resolve, reject){                //..... do something                if(success){                    resolve(arg);                }else {                    reject();                }            });        }        run(arg1)            .then(function(arg1){                //success                //do something            },function(arg1){                //wrong                //do something            })            .then(function(arg2){                //success                //do something            },function(arg2){                //wrong                //do something            })            .then(function(arg3){                //success                //do something            },function(arg3){                //wrong                //do something            });

简单来说,Promise规范就是定义一个function,这次不需要定义他的callback了,只需要return一个Promise对象,这个对象的构造函数接受一个匿名函数,匿名函数里定义这个function正常的功能,如果function执行成功了,调用resolve方法,这个方法可以接受一个参数,那么下个执行的函数将会接收到这个参数。反之,失败了定义执行reject。

调用时,执行该函数,在执行下一个函数时使用.then方法,正确执行对于的代码和错误执行对应的代码对应写入到then中,这样可以链式执行函数。
注意Promise执行之后,必须返回一个Promise对象才可执行下一个then方法,所以then方法中的函数一定返回Promise对象才可。

兼容性方面 高版本的主流浏览器都有内置的Promise对象,因为这个ES6的规范,较低版本的浏览器可以通过引入第三方的库来实现,例如bulebird。在nodejs中也无需npm模块,只需require(“Promise”);即可

下一个例子,一个动画效果 ,分别使用常规的方法实现,和Promise方法实现,对比下不同。
<!doctype html><!DOCTYPE html><html><head>    <title>Promise animate</title>    <style>        .ball {            width:40px;            height:40px;            border-radius:20px;        }        .ball1 {            background: red;        }        .ball2 {            background: blue;        }        .ball3 {            background: yellow;        }        .ball4 {            background: black;        }        .ball5 {            background: pink;        }        .ball6 {            background: green;        }    </style>    <script type="text/javascript" src="./node_modules/bluebird/js/browser/bluebird.js"></script></head><body>    <div class="ball ball1" style="margin-left:0;"></div>    <div class="ball ball2" style="margin-left:0;"></div>    <div class="ball ball3" style="margin-left:0;"></div>    <div class="ball ball4" style="margin-left:0;"></div>    <div class="ball ball5" style="margin-left:0;"></div>    <div class="ball ball6" style="margin-left:0;"></div>    <script>        var ball1 = document.querySelector('.ball1');        var ball2 = document.querySelector('.ball2');        var ball3 = document.querySelector('.ball3');        var ball4 = document.querySelector('.ball4');        var ball5 = document.querySelector('.ball5');        var ball6 = document.querySelector('.ball6');        var Promise = window.Promise;        promiseAnimate(ball1, 100)            .then(function() {                return promiseAnimate(ball2, 200);            })            .then(function() {                return promiseAnimate(ball3, 300);            })            .then(function() {                return promiseAnimate(ball3, 150);            })            .then(function() {                return promiseAnimate(ball2, 150);            })            .then(function() {                return promiseAnimate(ball1, 150);            });        function promiseAnimate(ball, distance){            return new Promise(function(resolve, reject){                _animate();                function _animate(){                    setTimeout(function(){                        var marginLeft = parseInt(ball.style.marginLeft, 10);                        if(marginLeft === distance){                            resolve();                        }else {                            if(marginLeft < distance){                                marginLeft++;                            }else {                                marginLeft--;                            }                            ball.style.marginLeft = marginLeft + "px";                            _animate();                        }                    }, 13);                }            });        }            animate(ball4, 100, function(){            animate(ball5, 200, function(){                animate(ball6, 300, function(){                    animate(ball6, 150, function(){                        animate(ball5, 150, function(){                            animate(ball4, 150, function(){                                //alert("done");                            });                        });                    });                });            });        });        function animate(ball, distance, cb){            setTimeout(function(){                var marginLeft = parseInt(ball.style.marginLeft, 10);                if(marginLeft === distance){                    cb && cb();                }else {                    if(marginLeft < distance){                        marginLeft++;                    }else {                        marginLeft--;                    }                    ball.style.marginLeft = marginLeft + "px";                    animate(ball, distance, cb);                }            }, 13);        }    </script></body></html>

0 0
原创粉丝点击