[英]Is this a correct way to use the Deferred object?
我正在构建一个需要列出产品类别和子类别的应用程序。
当用户选择一个类别时,与此类别相关的子类别将使用ajax从服务器加载,但前提是以后没有加载(在这种情况下,它们是从DOM加载的)。
代码: http : //jsbin.com/abijad/edit#javascript,html
var $form = $('#new-product-form');
$form.on( 'change', 'select.product-categories', function( e ) { //I'm using event delegation for a future feature...
getSubCategories( $(this).val() ).done( function( $subCategoriesEl ){
$form.find( 'select.product-subcategories' ).not( $subCategoriesEl ).hide();
$subCategoriesEl.show();
});
});
var getSubCategories = function( categoryId ) {
var dfd = $.Deferred(),
$alreadyisLoaded = $form.find( 'select.product-subcategories' ).map( function( idx, el ){
if( parseInt( $( this ).data( 'category' ), 10 ) === parseInt( categoryId, 10 ) ){
return el;
}
});
if( $alreadyisLoaded.length > 0 ){ //don't request subCategories that already are loaded
console.log( 'SubCategory loaded from DOM' );
dfd.resolve( $alreadyisLoaded );
} else {
var subCategoriesHtml = '<select data-category="' + categoryId + '" class="product-subcategories">';
$.get( '/', { //The ajax request will only be simulated
categoryId : categoryId
}, function ( result ) {
//simulate success :X
result = {"status":1,"data":[{"name":"Sub-Category I","id":1},{"name":"Sub-Category II","id":2},{"name":"Sub-Category III","id":3}]};
console.log( 'SubCategory loaded with Ajax' );
if( result.status === 1 ) { //Success
for( var subCategoryInfo in result.data) {
if( result.data.hasOwnProperty( subCategoryInfo ) ){
subCategoriesHtml += '<option value="' + result.data[subCategoryInfo].id + '">';
subCategoriesHtml += result.data[subCategoryInfo].name + '</option>';
}
}
subCategoriesHtml += '</select>';
var $subCategories = $( subCategoriesHtml ).hide().appendTo( $form );
dfd.resolve( $subCategories );
} else {
dfd.reject();
}
});
}
return dfd.promise();
};
<form id="new-product-form">
<select class="product-categories">
<option value="1">Category I</option>
<option value="2">Category II</option>
<option value="3">Category III</option>
<option value="4">Category IV</option>
<option value="5">Category V</option>
</select>
<select data-category="1" class="product-subcategories">
<option value="1">SubCategory I</option>
<option value="2">SubCategory II</option>
<option value="3">SubCategory III</option>
<option value="4">SubCategory IV</option>
<option value="5">SubCategory V</option>
</select>
</form>
因为代码到处都是回调,所以我决定使用jQuery Deferred对象,但是我不知道这是否是正确的实现。 有人可以告诉我我做了正确的事,还是我应该做不同的事情?
我看不到任何明显不正确的内容。 总而言之,您以正确的方式使用deferd:抽象出方法的可能双重同步特性。 话虽如此,如果这是我的代码库中出现的代码,这就是我的编写方式。 主要要点是:不要在数组中使用for in
,不要用数组构建字符串,一致的命名和间距,以及其他一些简洁的JS首选项。 这些只是一个口味问题,因此,做得很好:
(function() {
var getSubCategories = function ( categoryId ) {
categoryId = +categoryId;
return $.Deferred( function ( dfd ) {
var isLoaded = form.find( 'select.product-subcategories' )
.map( function ( index, el ) {
if ( +$( this ).data( 'category' ) === categoryId ) {
return el;
}
}),
markup = [ ];
if ( isLoaded.length ) {
console.log( 'SubCategory loaded from DOM' );
dfd.resolve( isLoaded );
} else {
markup.push( '<select data-category="' + categoryId + '" class="product-subcategories">' );
var request = $.ajax({
url: '/',
data: { categoryId: categoryId }
});
request.done( function ( result ) {
//simulate success :X
result = {"status":1,"data":[{"name":"Sub-Category I","id":1},{"name":"Sub-Category II","id":2},{"name":"Sub-Category III","id":3}]};
var status = result.status,
data = result.data,
i = 0,
il = data.length,
current;
console.log( 'SubCategory loaded with Ajax' );
if ( status !== 1 || !data ) {
dfd.reject();
return;
}
for ( current = data[ i ]; i < il; i++ ) {
markup.push( '<option value="' + current.id + '">' );
markup.push( current.name + '</option>' );
}
markup.push( '</select>' );
dfd.resolve( $( markup.join( '' ) ).hide().appendTo( form ) );
});
}
}).promise();
};
var form = $( '#new-product-form' )
.on( 'change', 'select.product-categories', function ( e ) {
getSubCategories( $( this ).val() )
.done( function( el ) {
form.find( 'select.product-subcategories' )
.not( el )
.hide()
el.show();
});
});
});
附带说明一下,只是想提出一点,如果ajax请求失败,您将不会处理任何问题。 在这种情况下,您将需要reject
,并确保编写fail
方法。 只是抬头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.