简体   繁体   English

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

[英]Is this a correct way to use the Deferred object?

I'm building a App that need to list the categories and subcategories of a Product. 我正在构建一个需要列出产品类别和子类别的应用程序。

When a user selects a category, the subcategories related to this category are loaded from the server with ajax, but only if they have not been loaded later (in this case they are loaded from the DOM). 当用户选择一个类别时,与此类别相关的子类别将使用ajax从服务器加载,但前提是以后没有加载(在这种情况下,它们是从DOM加载的)。

Code: http://jsbin.com/abijad/edit#javascript,html 代码: 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>

Because the code was getting full of callback here and there, I decided to use the jQuery Deferred object, but I do not know if this is the correct implementation. 因为代码到处都是回调,所以我决定使用jQuery Deferred对象,但是我不知道这是否是正确的实现。 Could someone tell me I did the right thing, or should I do differently? 有人可以告诉我我做了正确的事,还是我应该做不同的事情?

I don't see anything glaringly incorrect. 我看不到任何明显不正确的内容。 All in all, you are using the deferred in the correct fashion: to abstract away the possibly dual-synchronistic nature of your method. 总而言之,您以正确的方式使用deferd:抽象出方法的可能双重同步特性。 Now, that being said, if this were code appearing in my codebase, this is how I would write it. 话虽如此,如果这是我的代码库中出现的代码,这就是我的编写方式。 The main points being: don't use for in on arrays, build strings with arrays, consistent naming and spacing, and just some other terse JS preferences. 主要要点是:不要在数组中使用for in ,不要用数组构建字符串,一致的命名和间距,以及其他一些简洁的JS首选项。 These are a matter of taste, so otherwise, good job: 这些只是一个口味问题,因此,做得很好:

(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();
                });
        });
});

As a side note, just wanted to bring up that you don't have any handling of problems if the ajax request fails. 附带说明一下,只是想提出一点,如果ajax请求失败,您将不会处理任何问题。 You would need to reject in that case, and make sure you write fail methods. 在这种情况下,您将需要reject ,并确保编写fail方法。 Just a heads up. 只是抬头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在这种情况下,这是$ .Deferred的正确用法吗? - Is this the correct use of $.Deferred in this situation? Dojo:正确的方法来“延迟”延迟类型的范围 - Dojo: Correct way to 'Hitch' scope of deferred types 在这种情况下使用对象销毁的正确方法是什么? - What is the correct way to use object destructing in this situation? 这是使用带有函数的对象的正确方法吗? - Is this the correct way to use an object with a function inside it? 有没有一种方法可以在jQuery中创建延迟的对象包装器 - Is there a way to create a deferred object wrapper in jQuery 是否可以直接通过AJAX创建和使用Deferred对象? - Is it possible to create and use a Deferred object directly with AJAX? 正确的方法将JSDoc与匿名对象和该对象的功能一起使用 - Correct way to use JSDoc with anonymous object and functions of this object 使用JavaScript对DOM对象执行算术运算的正确方法是什么? - What is the correct way to use JavaScript to perform arithmetic on a DOM object? 将对象附加到数组中时使用扩展符号的正确方法? - Correct way to use spread notation when appending an object into an array? 对象解构的正确方法 - Correct way of object destructuring
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM