一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

大白话讲解Promise,搞懂jquery中的Promise

时间:2016-03-31 编辑:简简单单 来源:一聚教程网

先讲$.Deferred

jquery用$.Deferred实现了Promise规范,$.Deferred是个什么玩意呢?还是老方法,打印出来看看,先有个直观印象:

JavaScript

<textarea wrap="soft" class="crayon-plain print-no" data-settings="dblclick" readonly="" style="border: 0px; outline: none; display: block; -webkit-appearance: none; padding: 0px 5px; height: 58.5px; resize: none; overflow: auto; margin: 0px; position: absolute; opacity: 0; box-sizing: border-box; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; color: rgb(0, 0, 0); tab-size: 4; z-index: 0; font-size: 13px !important; line-!important; font-family: Monaco, MonacoRegular, 'Courier New', monospace !important; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;">

1

2

var def = $.Deferred();

console.log(def);


输出如下:


$.Deferred()返回一个对象,我们可以称之为Deferred对象,上面挂着一些熟悉的方法如:done、fail、then等。jquery就是用这个Deferred对象来注册异步操作的回调函数,修改并传递异步操作的状态。

Deferred对象的基本用法如下,为了不与ajax混淆,我们依旧举setTimeout的例子:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

function runAsync(){

    var def = $.Deferred();

    //做一些异步操作

    setTimeout(function(){

        console.log('执行完成');

        def.resolve('随便什么数据');

    }, 2000);

    return def;

}

runAsync().then(function(data){

    console.log(data)

});


在runAsync函数中,我们首先定义了一个def对象,然后进行一个延时操作,在2秒后调用def.resolve(),最后把def作为函数的返回。调用runAsync的时候将返回def对象,然后我们就可以.then来执行回调函数。


是不是感觉和ES6的Promise很像呢?我们来回忆一下第一篇中ES6的例子:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

function runAsync(){

    var p = new Promise(function(resolve, reject){

        //做一些异步操作

        setTimeout(function(){

            console.log('执行完成');

            resolve('随便什么数据');

        }, 2000);

    });

    return p;          

}

runAsync()


区别在何处一看便知。由于jquery的def对象本身就有resolve方法,所以我们在创建def对象的时候并未像ES6这样传入了一个函数参数,是空的。在后面可以直接def.resolve()这样调用。


这样也有一个弊端,因为执行runAsync()可以拿到def对象,而def对象上又有resolve方法,那么岂不是可以在外部就修改def的状态了?比如我把上面的代码修改如下:

JavaScript

1

2

3

4

5

var d = runAsync();

d.then(function(data){

    console.log(data)

});

d.resolve('在外部结束');


现象会如何呢?并不会在2秒后输出“执行完成”,而是直接输出“在外部结束”。因为我们在异步操作执行完成之前,没等他自己resolve,就在外部给resolve了。这显然是有风险的,比如你定义的一个异步操作并指定好回调函数,有可能被别人给提前结束掉,你的回调函数也就不能执行了。


怎么办?jquery提供了一个promise方法,就在def对象上,他可以返回一个受限的Deferred对象,所谓受限就是没有resolve、reject等方法,无法从外部来改变他的状态,用法如下:

JavaScript