繁体   English   中英

这是使用Deferred对象的正确方法吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM