- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我的代码:
<!DOCTYPE html>
<html>
<head>
<title>d3 Practice</title>
</head>
<body>
<script src="./vislibs/d3.v3.min.js"></script>
<canvas id="test" width="1024" height="768" style="border: 1px solid black;"></canvas>
<script>
function generate_data(size){
var randomX = d3.random.normal(width/2 , 80),
randomY = d3.random.normal(height/2, 80);
var data = d3.range(size).map(function() {
return [
randomX(),
randomY()
];
});
return data
}
function main() {
var canvasEl = d3.select('#test').node();
// get 2d context to draw on
var ctx = canvasEl.getContext('2d');
width = canvasEl.width
height = canvasEl.height
data=generate_data(20000000)
alert("data generated")
// set fill color of context
var x = 0
ctx.fillStyle = 'red';
batch_size = 10000
debugger // Cannot step into requestAnimationFrame(draw_loop) at all , freezing eternity
draw_loop = function () {
if (x<=data.length-1) {
for (i in d3.range(0,batch_size)){
//console.log(x)
ctx.fillRect(data[x][0], data[x][1], 2, 2);
x = x+1
}
setTimeout(draw_loop,100);
}
}
requestAnimationFrame(draw_loop)
//alert("done reqanim")
}
main()
//init()
</script>
</body>
</html>
这将在生成 generate_data(20000000)
后卡住浏览器,甚至无需转到 requestAnimationFrame(draw_loop)
。我在没有 requestAnimationFrame
或 setTimeout
的情况下进行了测试,并一次渲染所有内容,但工作正常,但它会卡住浏览器一点。卸载到服务器似乎是一个很好的解决方案,但我想知道为什么暂停(setTimeout 和 requestAnimiationFrame)会导致浏览器无限卡住而不是将控制权交给浏览器。
在 Linux 上测试,Chromium 版本 26.0.1410.43 (189671)。
浏览器的内存使用量约为 1.4 GB,仅在 generate_data(20000000)
完成后打开该脚本的一个选项卡,但我的笔记本电脑上有 6 GB 的可用内存。那么有没有什么有效的方法来处理呢? (不会导致无响应或无限卡住)
编辑:
这里正在工作 JSFiddle 2 mil rectangles
这将卡住您的浏览器。 20 mil rectangles
如果没有 setTimeout 或 requestAnimationFrame ,这将导致 1-2 次无响应,但可以很好地渲染到最后而不会卡住。 20 mil rectangles without pausing functions
概念证明,没有渲染代码,生成数据,数据生成后您将看到警报框,但浏览器一点击requestAnimationFrame就被卡住。 (2000万点)will freeze browser ,
function generate_data(size){
var randomX = d3.random.normal(width/2 , 80),
randomY = d3.random.normal(height/2, 80);
var data = d3.range(size).map(function() {
return [
randomX(),
randomY()
];
});
return data
}
function main() {
var canvasEl = d3.select('#test').node();
// get 2d context to draw on (the "bitmap" mentioned earlier)
var ctx = canvasEl.getContext('2d');
width = canvasEl.width
height = canvasEl.height
data=generate_data(20000000)
alert("data generated")
// set fill color of context
var x = 0
ctx.fillStyle = 'red';
batch_size = 10000
//debugger // Cannot step into requestAnimationFrame(draw_loop) at all , freezing eternity
draw_loop = function () {
if (x<=data.length-1) {
nada=""
x=x+batch_size
setTimeout(draw_loop,100);
}
}
requestAnimationFrame(draw_loop)
alert("done reqanim")
}
main()
最佳答案
Javascript 是一个单线程系统。像 setTimeout 这样本质上创建回调的函数仍然会杀死单线程系统。
编辑:
根据评论,有一些创造性的方法可以让单线程 Javascript 产生异步执行大型逻辑函数的错觉,从而释放执行点击处理程序等内容的过程。
@V3ss0n 根据代码中进程卡住发生的位置,您有以下几个选项:
1) 进程在创建数组期间卡住:将 2000 万个项目加载到数组中可能需要一段时间,我建议不要这样做。有不止一种方法可以解决这个问题,但我会尽可能地将繁重的循环逻辑移至 JavaScript 之外,并可能移至 Web 服务。这有其自身的挑战,例如尝试将 2000 万件元素发送回客户,这是一个坏主意。但是,如果您可以将其分成可管理的坐标组(最多 20-100),然后根据需要进行多个 Web 服务调用(使用 JQuery Ajax 方法 http://api.jquery.com/jQuery.ajax/ 之类的东西),那么您的 javascript 所需要担心的就是附加项目。这将在一段时间内向您传输数据,因此不要期望它是即时的,但如果浏览器在循环坐标创建函数 2000 万次时遇到困难,则不应卡住浏览器。
2) 渲染每个单独点期间进程卡住:对此的修复更具创意,如果您不想使用 Web 服务,也可以用于上述过程。首先看下面的代码:
var renderingCounter = 0;
var asyncTimer = null; // keep the render timer global to prevent duplicate renders from being run
function StartRender(){
// test if existing async render is running
if(asyncTimer != null){
// existing async timer, clear the timer and clear the canvas
clearInterval(asyncTimer);
renderingCounter = 0;
// code for clearing the canvas ..
};
// create interval object
var asyncTimer = setInterval(function (){
// at the begining of each start render, test if all points have been rendered
if(renderingCounter >= pointArray.length){
// kill the asynctimer
clearInterval(asyncTimer);
asyncTimer = null;
renderingCounter = 0; // reset the counter
return;
};
while(renderingCounter < 100){ // only draw 100 items
if(renderingCounter >= pointArray.length){ // make sure you are not out of array bounds
return;
};
// execute display code for that point
}; // loop
}, 40);
}
上面的代码将渲染过程分为 100 个点组。完成一组后,它会暂停 40 毫秒,这应该会在主线程上释放足够的时间,以允许继续执行其他项目(例如 UI)。全局变量renderingCounter将通过数组保持当前进度。如果函数在渲染期间被重新调用,代码还会检查当前正在运行的渲染计时器(在示例中,它会终止当前渲染并重置它)。如果渲染计时器仍然导致挂起,您可以增加暂停间隔。
这两种实现异步执行的方法应该提供足够的灵 active ,以允许从服务器端 Web 服务进行渲染或数据读取(如果您朝这个方向发展),同时仍然保持流畅的 ui
关于javascript - 我如何在浏览器端有效地处理巨大的javascript数组(2000万个坐标的数组)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16945006/
我有一个使用 css 列的下拉菜单,当我使用 jquery slide() 时,它会调整下拉框的大小,并重排内容直到达到完整高度。 这是一个工作示例 https://codepen.io/peterg
我有一个带有嵌套 ScrollViewer 的 Expander,如下所示: 代码(简化版)
我想在所有 ajax 调用之后调用一些 javascript 函数。我知道如何调用每个单独的 ajax 调用中的函数,如下所示: function xyz() { if (window.XMLHttp
我想将值从应用程序端传递到 api。在此 api 调用中传递图像、名字、电子邮件、电话和位置。在 Debug模式下,检查值不会被传递。 代码下方 File file = null;
我正在尝试在使用reportlab生成的pdf中的表格后插入分页符,我正在使用以下函数生成pdf: def render_to_pdf(template_src, context_dict): t
CBPeripheralManager 是否有推荐的方法来终止连接。到目前为止我发现的最好的方法就是干脆不响应动态值,然后 BLE 堆栈似乎关闭了连接,但这似乎很粗糙。 一定有更好的方法吗? 最佳答案
我的 API 的 REST 端位于以下地址:http://test.jll.aplikacje-dedykowane.pl/rest/warehouse/all 。现在,我尝试返回在此页面准备的 JS
我有以下 CPP 代码。我想做的是,当我的 native 端发生错误时,我会通知 Java 该错误。我用了How can I catch SIGSEGV (segmentation fault) an
限制对象的方法之一是像这样给函数添加限制 def ten_objects(): obj = Model.objects.all()[0:10] # limit to 10 retur
我目前在电信公司实习,这是一个专业,也是本科生。我有很多选择。据我所知,我知道独立应用程序端的 c、c++、c#、java 语言,在移动端我尝试进入 android 世界,也知道 php、mysql、
我想让我的边框底部看起来像这样: 有一个 flex 的末端。目前它看起来像这样: 我尝试使用的 CSS 是 border-bottom-right-radius: 10px;。代码如下所示:
我有一个 Flutter 项目,突然间,据我所知,我没有做任何特别的事情..Android 端开始显示错误,我完全迷路了,我完全不知道哪里出了问题,也不知道为什么会这样。 这就是我打开 android
我有一个自定义对象列表 (List) 。我需要将此数据发送到 React Native 端以显示在平面列表中。我该怎么做?这个列表出现在 类 NativeToReact(reactContext:Re
我有这个代码: #if defined(NOT_STANDALONE) JNIEXPORT void JNICALL sumTraces (JNIEnv* env, jclass caller,
我有一个定义一对多模型关系的 Django 应用程序。模型如下所示: from django.db import models # Create your models here. class Str
我有以下代码,它根据 IFrame 内容的大小调整 IFrame 的大小: function setIframeHeight(id) {
如何创建自定义过滤器 angularjs javascript Controller 端?我想通过 SegmentId 在名为段的数组中搜索,以创建过滤器,该过滤器通过 SegmentId 在段数组搜
我的代码在 netbeans 8.0.2 中我几乎尝试了所有方法,但没有结果。请帮助我。如何在 netbeans 中显示它? 最佳答案 您只需单击源包(源文件),它就会显示您的项目文件。 关于java
我想这是纯 C++ 问题和 OpenGL 问题之间的一种交叉。我有一个统一的缓冲区,并在其中分配 sizeof(ShaderData) 字节的空间。我在着色器的 GPU 端使用 std140 布局。
我对 Hadoop 中 reduce 端的文件合并过程的理解有问题,因为它在“Hadoop:权威指南”(Tom White)中有所描述。引用它: When all the map outputs ha
我是一名优秀的程序员,十分优秀!