簡體   English   中英

如何在解析 Jquery 或 Javascript 中的 CSV 文件時加快搜索速度?

[英]How to speed up search while parsing a CSV file in Jquery or Javascript?

我有一個 CSV 文件,其中包含大約 40K 條目和 3 列 - 值、城市和 Class

下面是結構:

Value    Class    City
111      lev 0    New York
112      lev 1    Winston
113      lev 2    Dakota
114      lev 2    Washington

Class lev-0 是 level-1 的父級,它是 lev-2 的父級 (lev-0>lev-1>lev-2)

現在我有 3 個 select 框父區域、子區域、子子區域

我為返回所選值的父區域設置了一個 onchange 偵聽器,然后通過 CSV 文件進行搜索,一旦將其下方的所有元素與 class = lev-1 匹配,則用於創建 Z99938282F04071859941E 區域的選項列表 Z99938282F04071859941E while 循環直到 class = lev-0 是循環停止的地方。

問題是,一旦我使用 select 元素,在 select 框被填充之前大約需要 3-4 秒,並且在很多時候它甚至會掛起瀏覽器。

我正在使用 Papa Parser 來解析 CSV

const csv = "https://example.com/locations.csv";
let results = [];
const csvData = Papa.parse(csv, {
  header: true,
  download: true,
  complete: response => {
    results = response.data;
  }
});

以下是使用值作為輸入獲取 Class 名稱和城市名稱的函數

function findCityByName(inputVal) {
  return results.filter(data => data.Value == inputVal)[0].City;
  }
function findClassbyValue(inputVal) {
  return results.filter(data => data.Value == inputVal)[0].Class;
  }

以下是為 select 框子區域創建選項值的代碼

function GetChildRegions(inputVal){
var inputVal2 = inputVal;
var currentObject = results.filter(data => data.Value == inputVal2)[0];
currentIndex = results.indexOf(currentObject);
//move to next object
currentObject =  results.filter(data => data)[currentIndex + 1];
currentClass = findClassbyValue(currentObject.Value);
var RegionDropOption;

while (currentClass != 'level-0') {
  
  if(currentClass == 'level-1'){
  RegionDropOption += '<option value="' + currentObject.Value + '">' + currentObject.City + '</option>\n';
  currentIndex = results.indexOf(currentObject);
  currentIndex++;
  currentObject = results.filter(data => data)[currentIndex];
  currentClass = findClassbyValue(currentObject.Value);
  }
}
return RegionDropOption;
}

以下是 jquery 在 Child Region Select Box on change event of Parent Region 中注入 html 代碼

jQuery("#Parent_region").change(function() {
var selectedMainRegion = jQuery('#Parent_region').find(":selected").val();
jQuery("#child_region").html(GetChildRegions(selectedMainRegion));  

});

如何讓搜索更快?

編輯:

添加緩存(記憶)

Momoizer Function

function memoizer(fun){
    let cache = {}
    return function (n){
        if (cache[n] != undefined ) {
          return cache[n]
        } else {
        console.log(n);
          **let result = fun(n)  // Result is Undefined here** 
          cache[n] = result
          return result
        }
    }
}

被記憶的功能。

function GetSubRegion(selectedMainRegion){
if (typeof(subRegWorker) != "undefined") {
subRegWorker.terminate();
}
subRegWorker = new Worker("subRegWorker.js");
subRegWorker.onmessage = function(e) {
var workData = e.data;
jQuery("#_sub_region").html(workData);
subRegWorker.terminate();
return workData;
}
subRegWorker.postMessage(selectedMainRegion);
}

示例 - var hello = GetSubRegion(123); 你好在這里是未定義的。 如何解決?

更改時致電已記憶的 Function

jQuery("#_main_region").change(function() {
var getCacheSub = memoizer(GetSubRegion);
var inputMainRegion = jQuery('#_main_region').find(":selected").val();
getCacheSub(inputMainRegion);
});

js是單線程的。 這個長循環是塊計算機。 你需要的是工人。 工人正在使用另一個線程。 例子

// main code
if ('serviceWorker' in navigator) { // check for browserr support
    var work = new Worker("http://localhost:5500/worker.js") // you need another js file for worker
    work.postMessage("message") // send any data
    work.addEventListener("wessage",function(e){
        console.log(e.data) // response of worker
    })
}

// worker file

self.postMessage("message"); // worker to main communicating 

self.addEventListener("message", function(event) {
console.log("Message from parent:", event.data); // main to worker communicating
});

如果您不想制作第二個文件。 https://github.com/keithwhor/multithread.js

自己翻譯

// worker
/**
 * optimized class
 * logic is save the answer. for to be faster next time.
 * @param {array} results
 * @constructor
 */
class csvParseOpti {
    constructor() {
        this.caches = []; // cache response for optimization.
        //  ex. caches:[{City:{inpVal:"Ankara",res:"0"},Class:blabal}]
        this.results; // parsed csv by Papa
        /** [
         {City: "Ankara", Class: "1", Value: 111},
         {City: "Mersin", Class: "1", Value: 112},
         {City: "İzmir", Class: "0", Value: 113}
         ] temp table
         */
        this.talkWidthMain();
    }

    /**
     * write talkWidthMain part for this function
     * @parm {string} csv
     */
    runPapa(csv) {
        let results = [];
        Papa.parse(csv, {
            header: true,
            download: true,
            worker: true,
            fastMode: true,
            complete: response => {
                results = response.data;
            }
        });
        return true;
    }

    /*
    * talk width main thread
    * */
    talkWidthMain() {
        self.addEventListener("message", (msg) => { // listen main
            console.log(msg)
            if (msg.data.func == "city") { // eğer ana çekidekden gelen mesaj da city varsa findCityByName()'i çalıştır
                self.postMessage(this.findCityByName(msg.data.value)); // komutun çıktısın döndür.
                // eğer istersen idde gönderebilirsin. cavpalrın karışmaması için.
            } // else diyer fonkisyonlar için aynısı
        })
    }


    /**
     * search in cache if not exist finds in array and push in cache.
     * do this for anothe functions
     * @param {string} inpVal
     * @public
     * @return {string}
     * */
    findCityByName(inpVal) { // your find function
        let cache = this.caches.filter(cache => cache.City.inpVal == inpVal); // check if this is used before
        if (cache && cache.length > 0) { // if is used return end of this function
            return cache[0].City.res;
        }
        // Not: if cache.City an cache.Class leangth's sum ara same as len of result. set null cahe
        cache = this.results.filter(data => data.City == inpVal)//[0].City; // else find in big array
        this.caches.push({City: {inpVal, res: cache}}); // and push in to caches
        return cache; // vala
    }
}

new csvParseOpti();
// main 
if ('serviceWorker' in navigator) { // check for browserr support
    var work = new Worker("opt.js") // you need another js file for worker
    work.postMessage({func:"city",value:"Mersin"}) // send any data
    work.addEventListener("message",function(e){
        console.log(e) // response of worker
    })
}

這只是緩存響應。

感謝@eay 指導使用工人和記憶

緩存問題解決如下 -

    var cache = {};
    function memoizer(fun){
        
        return function (n){
            if (cache[n] != undefined ) {
            jQuery("#_sub_region").html(cache[n]);  // This was changed
            return cache[n]
            } else {
            console.log(n);
              cache[n] = result
              return result
            }
        }
    }

function GetSubRegion(selectedMainRegion){
if (typeof(subRegWorker) != "undefined") {
subRegWorker.terminate();
}
subRegWorker = new Worker("subRegWorker.js");
subRegWorker.onmessage = function(e) {
var workData = e.data;
cache[n] = workData // This was changed
jQuery("#_sub_region").html(workData);
subRegWorker.terminate();
return workData;
}
subRegWorker.postMessage(selectedMainRegion);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM