gpt4 book ai didi

javascript - 如何修复阻塞的 JavaScript 进程?

转载 作者:行者123 更新时间:2023-12-03 12:41:46 24 4
gpt4 key购买 nike

一般问题

嗨,我尝试使用 setTimeout 将逻辑移动到进程,以便立即显示加载屏幕并在进程完成后更新页面。

有时它有效,有时则无效。现在我想我需要了解更多理论才能弄清这个问题的真相。

当网站阻止整个浏览器 (Firefox) 或选项卡中的所有内容 (Chrome) 时,是否总会出现编程错误?

这可能是抽象泄漏的情况(就像一个永不休眠且不允许 CPU 在其他进程上工作的 C/C++ 游戏循环)吗? 如果这个过程需要很长时间并且有很多工作要做,我是否必须编写一个与多个 setTimeout 一起使用的机制?

还有什么我需要调查/记住的吗?

详细信息

我已阅读https://softwareengineering.stackexchange.com/questions/202047/what-determines-which-javascript-functions-are-blocking-vs-non-blocking它似乎没有回答问题。

问题可以在这里看到: http://procgames.com/raidaces/

Firefox 有时会被阻止,并且在整个过程完成之前不会更新任何内容(很奇怪,因为我在调用加载过程之前在 Canvas 中渲染加载状态)。

在 Chrome 中,文本会被阻止(无法选择),直到该过程完成,因此我假设整个选项卡都被卡住。

发生的情况是:25 个图像 (1024x1024) 在 Canvas 中渲染,并使用 toDataURL 移动到 img 实体(因此客户端非常繁忙)。

也许我做错了什么?程序在 HTML 文件中启动:

        <div class=container>
<h1>Raid Aces</h1>

<canvas id="gameCanvas" width="800" height="600" onClick="toggleRunning(gameContext)"></canvas>
<div id="debugArea">The Epic Battles Of The Ancient Clans ... or whatever ...</div>
<canvas id="mapCanvas" width="128" height="128"></canvas>

<div class="clear"></div>
<div id="hiddenContentArea"></div>

<script>

var gameCanvas = document.getElementById('gameCanvas');
var gameContext = gameCanvas.getContext('2d');
var hiddenContentArea = document.getElementById('hiddenContentArea');

var mapCanvas = document.getElementById('mapCanvas');
var mapContext = mapCanvas.getContext('2d');

gameContext.beginPath();
gameContext.rect(0, 0, 800, 600);
gameContext.fillStyle = "#88BB88";
gameContext.fill();
gameContext.font = "bold 16px sans-serif";
gameContext.fillStyle = "#FFFFFF";
gameContext.fillText("Loading", 350, 294);

mapContext.beginPath();
mapContext.rect(0, 0, 128, 128);
mapContext.fillStyle = "#88BB88";
mapContext.fill();
mapContext.font = "bold 10px sans-serif";
mapContext.fillStyle = "#FFFFFF";
mapContext.fillText("Loading", 42, 62);

initEngine(gameContext);
initGame(gameContext, hiddenContentArea);

document.addEventListener('keydown', function(event) {
handleInputEvent(event, gameContext);
});
</script>
</div>

调用 initGame ...

function initGame(gameContext, hiddenContentArea) {

if (!engine.isInitialized) {
throw "error_engine_not_initialized";
}

var eventsModule = engine.getModule("events");
log("Rendering Map, please be patient!");
eventsModule.changeGameState(new GameStateLoading(engine));
}

...这就是异步调用应该实现的地方:

ModuleEvents.prototype.changeGameState = function(moduleGameState) {

var oldGameState = this.gameState;
if (oldGameState) {
oldGameState.uninit();
}

this.gameState = moduleGameState;
var callbackFunction = this.makeCallbackExecution(oldGameState,
this.gameState, this.eventBus);

setTimeout(callbackFunction, 10);
};

ModuleEvents.prototype.makeCallbackExecution = function(oldGameState,
newGameState, eventBus) {

return function() {
newGameState.init();
eventBus
.fireEvent(new EventGameStateChanged(oldGameState, newGameState));
};
};

最佳答案

我使用 Chrome 开发者工具 (CDT) 时间轴选项查看了您的项目,并注意到以下内容:

CDT Timeline view

我不是 CDT 专家,但似乎这 25 个计时器是同时设置的(在 gamestate_loading.js:109 的循环中)并且将同时触发。现在想象一下您是一个为网页提供服务的线程。你的职责是绘制 UI(可能响应用户)并执行 JS。但突然出现了 25 个 JS 任务以及常见的 GUI 请求。我不知道计时器调度的细节,但我不认为同时触发大量计时器是一个好主意。

是的,由于 javascript 的单线程特性,这 25 个计时器将被串行执行,一个接一个。

我建议您调查 WebWorkers 的适用性根据你的情况。它们的设计目的是为了将繁重的计算与 UI 分开。此外,您可能希望最大限度地优化在计时器回调中所做的工作(例如,最小化 DOM 和渲染操作)。

关于javascript - 如何修复阻塞的 JavaScript 进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23503766/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com