开发者

How to avoid 3 ajax calls?

I wrote some code that filters a province/state select field after you choose a country:

    var cache = {};

    function updateProvinceOptions($select, values, initial) {
            for(i in values) {
                    $select.append('<option value="'+values[i][0]+'">'+values[i][1]+'</option>');
            }
            $select.val(initial).trigger('change');
    }

    $('<select class="province" />').insertBefore('.province').change(function() { // insert select boxes beside hidden province inputs
            $(this).siblings('input.province').val($(this).val()); // update hidden input with current value
    });

    $('.country').change(function()开发者_StackOverflow社区 {
            var $countrySel = $(this);
            var $provSel = $countrySel.parent().parent().next().children('td').children('select.province');
            var $provInput = $provSel.siblings('input.province');
            var country = $countrySel.val();
            var province = $provInput.val();

            $provSel.empty();
            if(country in cache) {
                    updateProvinceOptions($provSel, cache[country], province);
            }
            else {
                    $provSel.addClass('loading');
                    $.getJSON('/get-provinces.json', {'country':country}, function(provinces) {
                            $provSel.removeClass('loading');
                            cache[country] = provinces;
                            updateProvinceOptions($provSel, provinces, province);
                    });
            }
    }).trigger('change');

It even caches the results so that if you, say, choose Canada, then US, and then Canada again, it doesn't have to hit the server for the list of Canadian provinces a second time. However, I'm displaying 3 of these on the page at the same time. When the page first loads, there's nothing in cache, so all 3 of em hit the server for a list of provinces because none of the ajax calls have returned yet.

Is there a relatively simple way to tell it to "wait" if an ajax call for that country is already in progress? Or should I even bother?


I would say maybe add a property to cache or some other object outside of your method to indicate whether the cache is currently being loaded. Set the value to true before you call the ajax method and then set it to false in the success function of the ajax call once it is complete. If that is true then you skip any subsequent calls until that value is false.

Just one possible solution.


Nevermind.. answered my own question again when responding to spinon... it wasn't that hard to add a "waiting" queue after all:

    var cache = {};
    var retrieving = {};

    function updateProvinceOptions($select, values, initial) {
            for(i in values) {
                    $select.append('<option value="'+values[i][0]+'">'+values[i][1]+'</option>');
            }
            $select.val(initial).trigger('change');
    }

    $('<select class="province" />').insertBefore('.province').change(function() { // insert select boxes beside hidden province inputs
            $(this).siblings('input.province').val($(this).val()); // update hidden input with current value
    });

    $('.country').change(function() {
            var $countrySel = $(this);
            var $provSel = $countrySel.closest('tr').next('tr').find('select.province');
            var $provInput = $provSel.siblings('input.province');
            var country = $countrySel.val();
            var province = $provInput.val();

            $provSel.empty();
            if(country in cache) {
                    updateProvinceOptions($provSel, cache[country], province);
            } else if(country in retrieving) {
                    retrieving[country].push($provSel);
            }
            else {
                    retrieving[country] = [$provSel]
                    $provSel.addClass('loading');
                    $.getJSON('/get-provinces.json', {'country':country}, function(provinces) {
                            $provSel.removeClass('loading');
                            cache[country] = provinces;
                            while(retrieving[country].length > 0) {
                                    $select = retrieving[country].pop();
                                    updateProvinceOptions($select, provinces, province);    
                            }                               
                    });
            }
    }).trigger('change');


I would say it depends on the use case. Does the user always have to pass through these elements? If so I may be inclined to grab all the data when the page loads or even send the data down with the page in the first place.

Also depends how many items you are dealing with, maybe autocomplete would be a better solution.

Would really need a better feel for the app to advise more strongly

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜