jQuery Deferred和Promise创建响应式应用程序详细介绍

2020-05-22 15:18:24易采站长站整理


$.fn.bindOnce = function( event, callback ) {
var element = $( this[ 0 ] ),
defer = element.data( “bind_once_defer_” + event );
if ( !defer ) {
defer = $.Deferred();
function deferCallback() {
element.unbind( event, deferCallback );
defer.resolveWith( this, arguments );
}
element.bind( event, deferCallback )
element.data( “bind_once_defer_” + event , defer );
}
return defer.done( callback ).promise();
};

该代码的工作原理如下:
•检查该元素是否已经绑定了一个给定事件的deferred对象
•如果没有,创建它,使它在触发该事件的第一时间解决
•然后在deferred上绑定给定的回调并返回promise
  代码虽然很冗长,但它会简化相关问题的处理。 让我们先定义一个辅助方法:

$.fn.firstClick = function( callback ) {
return this.bindOnce( “click”, callback );
};

然后,之前的逻辑可以重构如下:

var openPanel = $( “#myButton” ).firstClick();
openPanel.done( initializeData );
openPanel.done( showPanel );

如果我们需要执行一些动作,只有当面板打开以后,所有我们需要的是这样的:

openPanel.done(function() { /* perform specific action */ });

如果面板没有打开,行动将得到延迟到单击该按钮时。
组合助手
  单独看以上每个例子,promise的作用是有限的 。 然而,promise真正的力量是把它们混合在一起。
在第一次点击时加载面板内容并打开面板
  假如,我们有一个按钮,可以打开一个面板,请求其内容然后淡入内容。使用我们前面定义的助手方法,我们可以这样做:

var panel = $( “#myPanel” );
panel.firstClick(function() {
$.when(
$.get( “panel.html” ),
panel.slideDownPromise()
).done(function( ajaxResponse ) {
panel.html( ajaxResponse[ 0 ] ).fadeIn();
});
});

在第一次点击时载入图像并打开面板
  假如,我们已经的面板有内容,但我们只希望当第一次单击按钮时加载图像并且当所有图像加载成功后淡入图像。HTML代码如下:

<div id=”myPanel”>
<img data-src=”image1.png” />
<img data-src=”image2.png” />
<img data-src=”image3.png” />
<img data-src=”image4.png” />
</div>

我们使用data-src属性描述图片的真实路径。 那么使用promise助手来解决该用例的代码如下:

$( “#myButton” ).firstClick(function() {
var panel = $( “#myPanel” ),
promises = [];
$( “img”, panel ).each(function() {