2012-10-29 30 views
0

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

这个想法是,如果应用程序在线,那么我会通过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);   
}  
}); 
+4

这是堆栈溢出的主题,codereview.stackexchange.com代码审查问题。 – asawyer

回答

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格式,而不是以前的。

+0

感谢您的回复,这绝对是一种更加结构化的存储数据的方式。它提高了iPad上的速度,但它仍然没有我想要的那么快。我会考虑进一步破坏数据。 – gilmoreja

+0

现在哪部分缓慢? json的下载,或者它的处理。 –

+0

它在autoComplete中的处理似乎是问题。删除输入框中的条目时,速度特别慢 – gilmoreja