我需要检查重复的数据库名称并更改此名称以避免重复。我使用@JefréN。
建议的脚本function eliminateDuplicates() {
var repeats = {};
var error = false;
//cache inputs
var $inputs = $("input[type='text']");
//loop through inputs and update repeats
for (i = 0; i < $inputs.length; ++i) {
//cache current element
var cur = $inputs[i];
//remove class
$(cur).removeClass("double-error");
//get text of this element
var text = $(cur).val();
//no text -- continue
if (text === "") {
continue;
}
//first time we've came across this value -- intialize it's counter to 1
if ((text in repeats) === false) {
repeats[text] = 1;
}
//repeat offender. Increment its counter.
else {
repeats[text] = repeats[text] + 1;
}
//update the the value for this one
$(cur).val(text + "-" + repeats[text]);
}
return error; // always returns false since I'm not sure
// when it's supposed to return true.
}
所以脚本工作正常,但如果我有多达100个条目。但如果我有几千条记录,浏览器就会冻结。 Firefox崩溃了。如何通过添加一些时钟指针的某些加载线来防止浏览器冻结和崩溃?也许我需要使用一些setTimeout()函数或其他东西。请帮助防止此浏览器冻结和崩溃问题。
我试过了:
function processLargeArrayAsync(array, fn, maxTimePerChunk, context) {
context = context || window;
maxTimePerChunk = maxTimePerChunk || 200;
var index = 0;
function now() {
return new Date().getTime();
}
function doChunk() {
var startTime = now();
while (index < array.length && (now() - startTime) <= maxTimePerChunk) {
// callback called with args (value, index, array)
fn.call(context, array[index], index, array);
++index;
}
if (index < array.length) {
// set Timeout for async iteration
setTimeout(doChunk, 1);
}
}
doChunk();
}
-
processLargeArrayAsync(veryLargeArray, myCallback);
没有成功。 Chrome冻结,IE11资源管理器也崩溃了。怎么了? 我的记录显示在HTML表格中。
有些人建议使用网络工作者。也许有人在这里练习并有一个有效的例子吗?
答案 0 :(得分:0)
这是一个解决方案,使用OODK-JS通过网络工作者计算1.000.000个数组的总和。
此解决方案使用SynchronizedQueue基础类实现生产者/消费者设计模式:生产者(主线程)为数组的每个块生成任务并将其添加到队列。消费者(webworker)在队列中执行任务并执行它直到没有人离开。执行完所有任务后,生产者将显示最终结果
// main.js (producer)
OODK.config({
'path': {
'oodk': '../src',
'workspace': 'workspace'
}
});
OODK(function($, _){
$.import('{oodk}/foundation/utility/Thread', '[util.concurrent]', '{workspace}/project/Task');
// array helper class to handle arrays
var ArrayHelper = $.class(function($, µ, _){
$.static(function($, µ, _){
// slice an array into chunks using chunkLength argument
// as delimiter
$.public(function slice(arr, chunkLength){
return arr.reduce(function(arr, val, index){
var chunkIndex = Math.floor(index/chunkLength);
if(!arr[chunkIndex]) {
arr[chunkIndex] = [];
}
arr[chunkIndex].push(val);
return arr;
}, []);
});
// generate an array of len argument length
// containing random values
$.public(function random(len){
var arr = [];
for(var i =0; i<len; i++){
arr.push(Math.random()*10);
}
return arr;
})
});
});
// class to handle a pool of thread
var ThreadPool = $.class(function($, µ, _){
// number of threads to instantiate
$.private('num');
// queue to works with
$.private('queue');
$.public(function __initialize(num, queue){
_.num = num;
_.queue = queue;
});
// start the pool
$.public(function start(){
// bind listeners
var threadListener= $.new(Producer);
for(var i=0; i<_.num; i++){
// instantiate consumers
var consumer = $.new(OODK.foundation.util.Thread, "consumer.js");
$.on(consumer, 'thread.ready', threadListener);
consumer.start();
}
$.on(_.queue, 'synchronizedQueue.taskDone', threadListener);
});
});
// Event Listener for the thread
var Producer = $.implements(OODK.foundation.EventListener).class(function($, µ, _){
// number of task done
$.private('taskDone', 0);
// final result
$.private('finalResult', 0);
$.private(function __processEvent(evt){
if(evt.getType() === 'thread.ready'){
// the thread is ready, synchronize the queue with the current thread
queue.synchronize(evt.getTarget());
}else if(evt.getType() == 'synchronizedQueue.taskDone'){
//message received from the consumer that it has performed a task
_.taskDone++;
var cqueue = evt.getTarget();
var chunkResult = evt.getData();
_.finalResult += chunkResult;
jQuery('#chunksDone').text(_.taskDone);
if(cqueue.getCapacity() == _.taskDone){
// once all tasks are performed display the final result
$.log('final sum is ' + _.finalResult);
}else{
// each time a chunk is calculated display the intermediate result
$.log('intermediate result ' + _.finalResult);
}
}
});
});
// generate a large array of 1.000.000 random values
var myHugeArray = ArrayHelper.self.random(1000000);
// split this array into chunks of 2500 length
var chunks = ArrayHelper.self.slice(myHugeArray, 25000);
// instantiate a synchronized queue setted as size the number of chunks
var queue = $.new(OODK.foundation.util.concurrent.SynchronizedQueue, chunks.length);
// for each chunk create a task and add it to queue
for(var i=0; i<chunks.length; i++){
var chunk = chunks[i];
// create a task for each chunk of the array
var task = OODK.project.Task.self.factory(chunk);
// and add it to the queue
queue.put(task);
}
// instantiate a pool of 2 threads working on the given queue
var threadPool = $.new(ThreadPool, 2, queue);
// start the pool
threadPool.start();
$.log('calculate the sum of an array of 1.000.000 entries using 2 threads ...');
});
消费者(网络工作者)
//consumer.js
OODK.config({
'path': {
'oodk': '../src',
'workspace': 'workspace'
}
});
OODK(function($, _){
// import the concurrent API package as well as the task class
$.import('[util.concurrent]', '{workspace}/project/Task');
// start the synchronizer
OODK.foundation.util.concurrent.SynchronizedObject.self.start();
// EventListener Class to handle synchronized queue events
$.implements(OODK.foundation.EventListener).class(function Consumer($, µ, _){
$.protected(function __processEvent(evt){
if(evt.getType() == 'synchronizedQueue.ready'){
//queue is synchronized
var queue = evt.getTarget();
// bind listener
$.on(queue, 'synchronizedQueue.elementRetrieved', this);
// take a task: get the heap of the stack and delete it
queue.take();
}else if(evt.getType() == 'synchronizedQueue.elementRetrieved'){
// task is retrieved from the queue
var task = evt.getData();
var queue = evt.getTarget();
// execute the task
var result = task.execute();
// notify the producer that the task is done
queue.notify('synchronizedQueue.taskDone', result);
if(queue.remainingElements()>0){
// at least one task is still in the queue, take it
queue.take();
}
}
});
});
var threadListener = $.new(_.Consumer);
// global listener for the synchronizedQueue.ready event
// triggered when the synchronzied queue is synchronized with this thread
$.on('synchronizedQueue.ready', threadListener);
});
实现自定义逻辑的任务类
OODK('project', function($, _){
$.public().implements(OODK.foundation.Serializable).class(function Task($, µ, _){
// the array chunk to calculate
$.private('chunk');
$.public(function __initialize(chunk){
_.chunk = chunk;
});
// calculate the sum of all entries of a chunk
// implements the custom logic here
$.public(function execute(){
var result = 0;
for(var i=0; i<_.chunk.length; i++){
result += _.chunk[i];
}
return result;
});
$.static(function($, µ, _){
$.public(function factory(chunk){
var task = $.new($.ns.Task, chunk);
return task;
});
});
});
});
答案 1 :(得分:0)
我认为代码中最繁琐的部分是DOM访问:获取输入值并更新它们。
根据webworkers documentation,网络工作者有其局限性,其中一个是DOM操作。所以我放弃了那个选项。
为了解决问题,我会这样做:
eliminateDuplicates
算法(加快速度)。eliminateDuplicates
异步:将元素集划分为较小的元素,并在不同的事件循环tick(setTimeout)中执行每个计算。在这里,我向您介绍我提出的解决方案。希望它能为您提供一些想法并帮助您解决问题。
首先,我调整了一点eliminateDuplicates
(我称之为modifyDOM
)
function modifyDOM(elements, repeats) {
var input, text, i = 0;
for (; i < elements.length; i++) {
input = elements[i];
text = input.value;
// Remove class.
input.className = input.className.replace(/\bdouble-error\b/, '');
if (text) {
repeats[text] = ~~repeats[text] + 1;
input.value = text + "-" + repeats[text];
}
}
}
我避免在主循环中使用jQuery,因为它的包装使事情变慢,在你的情况下它不值得使用它。这些微小的变化改善了每10,000个元素100毫秒的性能(给它或采取)。
我创建了两个使用modifyDOM
的函数:一个是异步的,另一个是同步的。
function parseElementsNonBlocking(elements, maxChunkSize) {
var repeats = {},
nChunks = Math.floor(elements/maxChunkSize),
i = 0,
j = 1;
//loop through inputs and update repeats
for(; i < nChunks; i++, j++) {
setTimeout(modifyDOM.bind(null, elements.slice(i, j*maxChunkSize), repeats), 0);
}
// Rest
setTimeout(modifyDOM.bind(null, elements.slice(i), repeats), 0);
}
function parseElementsBlocking(elements) {
var repeats = {};
//loop through inputs and update repeats
modifyDOM(elements, repeats);
}
最后,为了测试所有内容,这是一个在DOM准备就绪时执行并创建10.000输入的函数。然后输出运行上述任何方法所需的时间。
$(function () {
var inputsDiv = $('#inputs'), i, time;
for (i = 0; i < 10000; i++) {
var val = i % 3 === 0 ? 'Mickey' : (i % 3 === 1 ? 'Mouse' : '');
inputsDiv.append('<input type="text" class="double-error" name="FirstName" value="' + val + '">');
}
time = Date.now();
//parseElementsBlocking($("input[type='text']"));
parseElementsNonBlocking($("input[type='text']"), 100);
console.log(Date.now() - time);
});
这里有fiddle来测试它。