Nik*_*ola 1 javascript iphone jquery mobile-safari
我有一个Web应用程序,我将(通过ajax)一个字典文件(1MB)加载到javascript数组中.我找到了Mobile Safari在10秒后崩溃的原因.但现在我想知道的是如何解决这个问题?
在上面的链接上,答案建议使用setInterval,但这意味着我必须将一个字典文件分块,然后逐个加载.这肯定可以完成,但我必须考虑到互联网的速度制作了很多块,并且要加载页面需要太多的请求(如果我使块太大,可能会发生一些移动用户将无法在给定的10秒周期内下载块.
所以,我的问题是:有没有人遇到过这种问题,你是怎么做到的?理解正确方向的普遍推动.
编辑:这是我用来加载字典的js代码:
var dict = new Trie();
$.ajax({
url: 'data/dictionary_342k_uppercase.txt',
async: true,
success: function (data) {
var words = data.split('\n');
for (var i = words.length - 1; i >= 0; i--) {
dict.insert(words[i]);
}
},
error: function(){
$('#loading-message').text("Problem s rje?nikom");
}
});
Run Code Online (Sandbox Code Playgroud)
Trie.js:
function Trie () {
var ALPHABET_SIZE = 30;
var ASCII_OFFSET = 'A'.charCodeAt();
this.children = null;
this.isEndOfWord = false;
this.contains = function (str) {
var curNode = this;
for (var i = 0; i < str.length; i++) {
var idx = str.charCodeAt(i) - ASCII_OFFSET;
if (curNode.children && curNode.children[idx]) {
curNode = curNode.children[idx];
} else {
return false;
}
}
return curNode.isEndOfWord;
}
this.has = function (ch) {
if (this.children) {
return this.children[ch.charCodeAt() - ASCII_OFFSET] != undefined;
}
return false;
}
this.next = function (ch) {
if (this.children) {
return this.children[ch.charCodeAt() - ASCII_OFFSET];
}
return undefined;
}
this.insert = function (str) {
var curNode = this;
for (var i = 0; i < str.length; i++) {
var idx = str.charCodeAt(i) - ASCII_OFFSET;
if (curNode.children == null) {
curNode.children = new Array(ALPHABET_SIZE);
curNode = curNode.children[idx] = new Trie();
} else if (curNode.children[idx]) {
curNode = curNode.children[idx];
} else {
curNode = curNode.children[idx] = new Trie();
}
}
curNode.isEndOfWord = true;
return curNode;
}
}
Run Code Online (Sandbox Code Playgroud)
一旦开始在JS中进行处理,这是一个非常常见的问题.如果Mobile Safari问题是原因,那么你想要做的是弄清楚CPU时间在这里的位置.
我假设它是dict.insert()循环而不是data.split()调用(这将更难管理).
这里的想法是将dict.insert()循环分成功能块,这些功能块可以在顺序循环中异步调用(这是setupBuildActions函数所做的).在第一个块之后,每个后续块都被调用via setTimeout,这有效地重置了JS运行时中的函数时间计数器(这似乎正在扼杀你的进程).
使用Sequencer功能意味着您还可以控制函数的运行顺序(它们始终按照它们在此处生成的顺序运行,并且不会同时调度两个或多个函数执行).这比setTimeout没有回调的数千个呼叫更有效.您的代码保留对执行顺序的控制(这也意味着您可以在执行期间进行更改),并且JS运行时不会因计划的执行请求而过载.
您可能还想查看https://github.com/michiel/sequencer-js上的节点项目以获取更多测序示例,并查看http://ejohn.org/blog/how-javascript-timers-work/以获取解释setTimeout在不同的平台上.
var dict = new Trie();
// These vars are accessible from all the other functions we're setting up and
// running here
var BLOCKSIZE = 500;
var words = [];
var buildActions = [];
function Sequencer(funcs) {
(function() {
if (funcs.length !== 0) {
funcs.shift()(arguments.callee);
}
})();
}
// Build an Array with functions that can be called async (using setTimeout)
function setupBuildActions() {
for (var offset=0; offset<words.length; offset+= BLOCKSIZE) {
buildActions.push((function(offset) {
return function(callback) {
for (var i=offset; i < offset + BLOCKSIZE ; i++) {
if (words[i] !== null) { // ugly check for code brevity
dict.insert(words[i]);
}
}
// This releases control before running the next dict.insert loop
setTimeout(callback, 0);
};
})(offset));
}
}
$.ajax({
url: 'data/dictionary_342k_uppercase.txt',
async: true,
success: function (data) {
// You might want to split and setup these calls
// in a setTimeout if the problem persists and you need to narrow it down
words = data.split('\n');
setupBuildActions();
new Sequencer(buildActions);
},
error: function(){
$('#loading-message').text("Problem s rje?nikom");
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
486 次 |
| 最近记录: |