显然,这不好。我发个异步请求,还没收到数据就让人在外部给我结束了。。。。。。。
当然这个坑jQuery肯定会填的,在Deferred对象上有一个promise方法,是一个受限的Deferred对象
<script> function runAsync(){ var def = $.Deferred(); //做一些异步操作 setTimeout(function(){ console.log('执行完成'); def.resolve('请求成功之后返回的数据'); }, 2000); return def.promise(); //就在这里调用 } </script>
所谓受限的Deferred对象,就是没有resolve和reject方法的Deferred对象。这样就无法在外边改变Deferred对象的状态了。
Deferred对象的then方法和done、fail语法糖
我们知道,在ES6的Promise规范中,then方法接受两个参数,分别是执行完成和执行失败的回调,而jquery中进行了增强,还可以接受第三个参数,就是在pending状态时的回调,如下:
deferred.then( doneFilter [, failFilter ] [, progressFilter ] )
then方法:
<script> function runAsync(){ var def = $.Deferred(); //做一些异步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的随机数 if(num<=5){ def.resolve(num); } else{ def.reject('数字太大了'); } }, 2000); return def.promise(); //就在这里调用 } runAsync().then(function(d){ console.log("resolve"); console.log(d); },function(d){ console.log("reject"); console.log(d); }) </script>
Deferred对象的then方法也是可以进行链式操作的。
done,fail语法糖,分别用来指定执行完成和执行失败的回调,与这段代码是等价的:
<script> function runAsync(){ var def = $.Deferred(); //做一些异步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的随机数 if(num<=5){ def.resolve(num); } else{ def.reject('数字太大了'); } }, 2000); return def.promise(); //就在这里调用 } runAsync().done(function(d){ console.log("resolve"); console.log(d); }).fail(function(d){ console.log("reject"); console.log(d); }) </script>
always的用法
jquery的Deferred对象上还有一个always方法,不论执行完成还是执行失败,always都会执行,有点类似ajax中的complete。
$.when的用法
jquery中,还有一个$.when方法来实现Promise,与ES6中的all方法功能一样,并行执行异步操作,在所有的异步操作执行完后才执行回调函数。不过$.when并没有定义在$.Deferred中,看名字就知道,$.when,它是一个单独的方法。与ES6的all的参数稍有区别,它接受的并不是数组,而是多个Deferred对象,如下: