2012-01-31 2 views
1

제품의 카테고리와 하위 카테고리를 나열해야하는 앱을 만들고 있습니다.Deferred 오브젝트를 사용하는 올바른 방법입니까?

사용자가 카테고리를 선택하면이 카테고리와 관련된 하위 카테고리가 서버에서 아약스로로드되지만 나중에로드되지 않은 경우에만 (이 경우 DOM에서로드됩니다).

코드 : 코드가 여기 저기 콜백의 전체지고 있었기 때문에, 나는 jQuery를 이연 객체를 사용하기로 결정하지만,이는 경우 나도 몰라 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> 

올바른 구현. 누군가 내가 옳은 일을했다고 말해도 될까요, 아니면 다르게해야합니까?

+0

링크와 함께 질문에 관련 코드를 적어주십시오. 목표는 SO를 가능한 한 자급 자족하도록 유지하는 것입니다. 외부 사이트가 사라지더라도 문제는 여전히 관련성이 있어야합니다. –

+0

@JamesMontagne 편집을 참조하십시오. – JCM

+0

난 그냥 지연된 개체를 캐싱하고 결국 큰 범주/하위 범주 상황에서 숨겨진 요소의 큰 숫자를 피하기 위해 각 후속 변경 옵션을 다시 작성했을 것입니다,하지만 그 외에, 당신은 무엇을 가지고 작동합니다 요소의 수가 너무 커지지 않는 한 오래. –

답변

1

눈부신 부분이 보이지 않습니다. 결국, 당신은 올바른 방식으로 연기 된 것을 사용하고 있습니다 : 당신의 방법의 이중 동기 성을 추상화하는 것입니다. 자, 이것이 코드베이스에 나타나는 코드라면, 필자가 작성하는 방법입니다. 요점은 배열에 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(); 
       }); 
     }); 
}); 

:이, 그래서 그렇지 않으면 좋은 직장 취향의 문제입니다. 이 경우 reject이 필요하고 fail 메소드를 작성해야합니다. 그냥 머리를 올려.

+0

헤드 감사합니다. 한 가지 질문, 변수 앞에 더하기를 붙이면 정수로 변환됩니까? – JCM

+0

JavaScript unary plus 연산자를 사용하면 값을 숫자로 변환하려는 시도가 아직 없으면 시도합니다. 쉽고 빠릅니다 : https://developer.mozilla.org/en/JavaScript/Reference/Operators/Arithmetic_Operators#section_6 – Eli

관련 문제