[英]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.