JSON和自动完成的性能问题

时间:2012-10-29 19:53:16

标签: javascript jquery json performance jquery-autocomplete

我正在尝试编写一个可以使用应用程序缓存和本地存储等技术在线和离线工作的应用程序。我正在使用jQuery mobile和jqm自动完成解决方案,可在此处找到http://andymatthews.net/code/autocomplete/

这个想法是,如果应用程序在线,那么我将通过ajax调用远程可访问的函数来设置数据。所做的ajax调用会带回事件,国家和医院的数据。一旦返回数据,我就在localStorage中设置数据。

如果数据已经存在于localStorage中,那么我可以在离线时继续,因为我不必依赖于ajax调用。

在iPad /移动设备上运行时,我遇到了此代码的性能问题。涉及医院数据的地方。医院会返回大量数据,请参阅下面的医院数据JSON样本。它可能在桌面上有点慢,但几乎没有那么糟糕。

任何人都可以看到我对下面代码的任何改进,以提高性能。

JSON医院数据示例

{ "hospitals" : { 
  "1" : { "country" : "AD",
      "label" : "CAIXA ANDORRANA SEGURETAT SOCIAL"
    },
  "10" : { "country" : "AE",
      "label" : "Advance Intl Pharmaceuticals"
    },
  "100" : { "country" : "AT",
      "label" : "BIO-KLIMA"
    },
  "1000" : { "country" : "BE",
      "label" : "Seulin Nicolas SPRL"
    },
  "10000" : { "country" : "ES",
      "label" : "Dental 3"
    },
  "10001" : { "country" : "ES",
      "label" : "PROTESIS DENTAL MACHUCA PULIDO"
    },
  "10002" : { "country" : "ES",
      "label" : "JUST IMPLANTS, S.L."
    },
  "10003" : { "country" : "ES",
      "label" : "CTRO DENTAL AGRIC ONUBENSE DR.DAMIA"
    },
  "10004" : { "country" : "ES",
      "label" : "HTAL. VIRGEN DE ALTAGRACIA"
    },
  "10005" : { "country" : "ES",
      "label" : "HOSPITAL INFANTA CRISTINA"
    }....


/*global document,localStorage,alert,navigator: false, console: false, $: false */

$(document).ready(function () {
//ECMAScript 5 - It catches some common coding bloopers, throwing exceptions. http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
//It prevents, or throws errors, when relatively "unsafe" actions are taken (such as gaining access to the global object).
//It prevents, or throws errors, when relatively "unsafe" actions are taken (such as gaining access to the global object).
"use strict";

//initialise online/offline workflow variables
var continueWorkingOnline, continueWorkingOffline, availableEvents, availableHospitals, availableCountries, availableCities;
continueWorkingOnline = navigator.onLine;

var getLocalItems = function () {

    var localItems = [];    
    availableEvents = localStorage.getItem('eventData');
    availableHospitals = localStorage.getItem('hospitalData');
    availableCountries = localStorage.getItem('countryData');

    if (availableEvents) {
        //only create the array if availableEvents exists
        localItems[0] = [];
        localItems[0].push(availableEvents);
    }
    if (availableCountries) {
        //only create the array if availableCountries exists
        localItems[1] = [];
        localItems[1].push(availableCountries);
    }
    if (availableHospitals) {
        //only create the array if availableHospitals exists
        localItems[2] = [];
        localItems[2].push(availableHospitals);
    }
    if (availableCities) {
        //only create the array if availableHospitals exists
        localItems[3] = [];
        localItems[3].push(availableCities);
    }
    return localItems;              
};


//Check to see if there are 3 local items. Events, Countries, Cities. If true we know we can still run page off line
continueWorkingOffline = getLocalItems().length === 3  ? true: false; 

//Does what is says on the tin
var populateEventsDropDown = function (data) {      
    var eventsDropDown = $('#eventSelection');

    var item = data.events;
    $.each(item, function (i) {
        eventsDropDown.append($('<option></option>').val(item[i].id).html(item[i].name));
    });
};

//Called once getData's success call back is fired
var setFormData = function setData(data, storageName) {
    //localStorage.setItem(storageName, data);
    localStorage.setItem(storageName, data);
};

//This function is only called if continueWorkingOnline === true
var getRemoteFormData = function getData(ajaxURL, storageName) {
    $.ajax({
        url: ajaxURL,
        type: "POST",
        data: '',
        success: function (data) {
            setFormData(data, storageName);             
        }           
    });
};

//Function for autoComplete on Hospital data
var autoCompleteDataHospitals = function (sourceData) {

    var domID = '#hospitalSearchField';
    var country = $('#hiddenCountryID').val();

    var items = $.map(sourceData, function (obj) { 
        if (obj.country === country) {
            return obj;
        } 
    });     

    $(domID).autocomplete({
        target: $('#hospitalSuggestions'),
        source: items,
        callback: function (e) {
            var $a = $(e.currentTarget);
            $(domID).val($a.data('autocomplete').label);                                        
            $(domID).autocomplete('clear');
        }
    });
};  

//Function for autoComplete on Country data
var autoCompleteDataCountries = function (sourceData) {

    var domID = '#countrySearchField';
    var domHiddenID = '#hiddenCountryID';

    var items = $.map(sourceData, function (obj) { 
        return obj; 
    }); 

    $(domID).autocomplete({
        target: $('#countrySuggestions'),
        source: items,
        callback: function (e) {

            var $a = $(e.currentTarget);
            $(domID).val($a.data('autocomplete').label);                                        
            $(domID).autocomplete('clear');
            $(domHiddenID).val($a.data('autocomplete').value);

            //enable field to enter Hospital
            $('#hospitalSearchField').textinput('enable');

            //Call to autoComplete function for Hospitals
            autoCompleteDataHospitals(availableHospitals.hospitals);
        }
    });     
};

if (continueWorkingOnline === false && continueWorkingOffline === false) {
    alert("For best results this form should be initiated online. You can still use this but auto complete features will be disabled");
}

if (continueWorkingOnline === true && continueWorkingOffline === false) {               
    getRemoteFormData('templates/cfc/Events.cfc?method=getEventsArray', 'eventData');       
    getRemoteFormData('templates/cfc/Countries.cfc?method=getCountriesArray', 'countryData');
    getRemoteFormData('templates/cfc/Hospitals.cfc?method=getHospitalsArray', 'hospitalData');

    $(document).ajaxStop(function () {
        //set the variables once localStorage has been set

        availableEvents = JSON.parse(localStorage.getItem("eventData"));
        availableHospitals = JSON.parse(localStorage.getItem('hospitalData'));
        availableCountries = JSON.parse(localStorage.getItem('countryData'));

        //Inserts data into the events drop down
        populateEventsDropDown(availableEvents);

        autoCompleteDataCountries(availableCountries.countries);            
    });
}

if (continueWorkingOnline === true && continueWorkingOffline === true) {                
    //get the localStorage which we know exists because of continueWorkingOffline is true

    availableEvents = JSON.parse(localStorage.getItem('eventData'));
    availableHospitals = JSON.parse(localStorage.getItem('hospitalData'));
    availableCountries = JSON.parse(localStorage.getItem('countryData'));

    //Inserts data into the events drop down
    populateEventsDropDown(availableEvents);

    autoCompleteDataCountries(availableCountries.countries);        
}       
});

1 个答案:

答案 0 :(得分:1)

如果你的瓶颈是下载那个庞大的json文件,那么减少它的瓶颈的唯一方法就是缩小它或者发送更少的数据。例如,您可以按国家/地区对医院进行排序并存储数组而不是带有键的对象,以使json变小,而不是一遍又一遍地重复键。

{
    "AD":[
        "CAIXA ANDORRANA SEGURETAT SOCIAL"
    ],
    "AE":[
        "Advance Intl Pharmaceuticals"
    ],
    ...
    "ES":[
        "Dental 3",
        "Dental 4",
        "Dental 5"
    ]
}

如果id字段很重要,请使用

    ...
    "ES":[
        ["10000","Dental 3"],
        ["10001","Dental 4"],
        ["10002","Dental 5"]
    ]

您当然需要更新其余代码以使用此json格式而不是之前的格式。