Javascript 这是使用延迟对象的正确方法吗?
我正在构建一个应用程序,需要列出产品的类别和子类别 当用户选择一个类别时,与该类别相关的子类别将通过ajax从服务器加载,但只有在以后没有加载时,才会从DOM加载 代码:Javascript 这是使用延迟对象的正确方法吗?,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,我正在构建一个应用程序,需要列出产品的类别和子类别 当用户选择一个类别时,与该类别相关的子类别将通过ajax从服务器加载,但只有在以后没有加载时,才会从DOM加载 代码: 因为代码中到处都是回调,我决定使用jquerydeferred对象,但我不知道这是否是正确的实现。有人能告诉我,我做了正确的事情,还是应该做不同的事情?我看不出有什么明显的错误。总之,您正在以正确的方式使用延迟:抽象出您的方法可能具有的双重同步性。现在,也就是说,如果这是出现在我的代码库中的代码,我会这样写。要点是:不要在数组
因为代码中到处都是回调,我决定使用jquerydeferred对象,但我不知道这是否是正确的实现。有人能告诉我,我做了正确的事情,还是应该做不同的事情?我看不出有什么明显的错误。总之,您正在以正确的方式使用延迟:抽象出您的方法可能具有的双重同步性。现在,也就是说,如果这是出现在我的代码库中的代码,我会这样写。要点是:不要在数组中使用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请求失败,您不会有任何问题处理。在这种情况下,您需要拒绝,并确保编写失败方法。只是提醒一下。我没有看到任何明显不正确的地方。总之,您正在以正确的方式使用延迟:抽象出您的方法可能具有的双重同步性。现在,也就是说,如果这是出现在我的代码库中的代码,我会这样写。要点是:不要在数组中使用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请求失败,您不会有任何问题处理。在这种情况下,您需要拒绝,并确保编写失败方法。请注意。除了链接外,请在问题中包含相关代码。目的是尽可能保持自给自足。如果外部站点消失,问题仍然应该是相关的。@JamesMontagne请参见编辑。我会缓存延迟对象,并在每次后续更改中重新构建选项,以避免在非常大的类别/子类别情况下最终有大量隐藏元素,但除此之外,只要元素的数量不太大,你所拥有的就可以使用。除了链接外,请在问题中包含相关代码。目的是尽可能保持自给自足。如果外部站点消失,问题仍然应该是相关的。@JamesMontagne请参见编辑。我会缓存延迟对象,并在每次后续更改中重新构建选项,以避免在非常大的类别/子类别情况下最终有大量隐藏元素,但除此之外,只要元素的数量不太大,你所拥有的就可以工作。谢谢你的提醒。只有一个问题,在变量前面加一个加号可以将其转换为整数?使用JavaScript一元加号运算符可以尝试将一个值转换为一个数字(如果它还没有)。这很简单也很快:谢谢你的提醒。只有一个问题,在变量前面加一个加号可以将其转换为整数?使用JavaScript一元加号运算符可以尝试将一个值转换为一个数字(如果它还没有)。它既简单又快速:
(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();
});
});
});