读jquery技术内幕(jquery1.7版本)遇到的问题

<script src="jquery.js"></script>
<script>
function fn1(args){console.log('fn1',args);}
function fn2(args){console.log('fn2',args);}
var defer=$.Deferred(),
    filtered=defer.pipe(function(value){return value*2;});
defer.done(fn1);
filtered.done(fn2);
defer.resolve(5);
/*输出
fn2 10
fn1 5
*/
</script>

为什么是先执行fn2再执行fn1?

阅读 2k
2 个回答

在执行filtered=defer.pipe(function(value){return value*2;});的时候,会返回$.Deferred(fn).promise();$.Deferred(fn)中的fn会在$.Deferred()结束之前执行,pipe方法中的$.Deferred(fn)的fn会执行deferred.done(匿名函数。。。),这个匿名函数负责执行pipe方法返回的新的异步队列,要先于defer.done(fn1);所以先执行匿名函数匿名函数执行fn2,最后执行fn1。表达能力不是很好,所以说的不是很清楚orz。。。

感觉说的有点乱,其实总结就是,在 defer.resolve(5) 之前,并没有任何函数被执行,它们只是在定义 什么时候干什么事, 如果你能理解这一点,下边这些你应该就不会觉得乱了。


我没有怎么学习过 jQuery, 但是看这个 API,应该是这样的:

filtered = defer.pipe(v => v * 2) 这里为 defer 定义了一个流水线任务(即 pipe,这个东西有很多翻译,我习惯理解成流水线,pipe 多数情况下是允许你不停叠加任务的);

defer.done(fn1) 是为 defer 定义了:当前边 pipe里所有的任务都执行完后,执行fn1

filtered.done(fn2) 是说 filtered 本身执行完后执行 fn2

defer.resolve(5) 从此时开始,表明对 defer (和 defer 上定义的一系列 pipe 任务)已经定义完成,开始执行。

所以你可以看到输出时是这样的:

defer.resolve(5)
// 开始执行 defer
// 因为前边定义了 filtered = derfer.pipe(v => v * 2),所以要先把流水线上的任务执行完
// 也就是说 filtered 会拿到一个10作为参数
// filtered.done 就是通知你 filtered 本身的事情做完了,相当于一个事件回调。
fn2(10) // 这个 10 就是 defer.pipe 里那个函数的结果
//filtered 全部事情都完成了,现在就继续回到 defer 的任务上
// defer 的任务除了 filtered 就没了,那么就执行 defer.done
// 而 v => v * 2 是 filtered 时所执行的操作,所以此时 defer 手上的不是10而仍然是5
fn1(5)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题