调试
在我们编写更多代码之前,我们需要一些在出现问题时使用的调试工具。
为Panic启用日志记录
我们的 wasm-pack-template
附带了 console_error_panic_hook
crate 是一个可选的默认开启的依赖项,可以在 wasm-game-of-life/src/utils.rs
中看到已配置了。
我们需要做的就是在初始化函数或常用代码路径中安装 hooks
。
我们可以在 wasm-game-of-life/src/lib.rs
中的,Universe::new
构造函数里面调用它:
pub fn new() -> Universe {
utils::set_panic_hook();
// ...
}
加入日志到游戏中
运用 console.log 函数,是由 web-sys
添加一些记录日志,记录 Universe::tick
函数的每个 Cell
。
首先,在 wasm-game-of-life/Cargo.toml
添加 web-sys
依赖项,并启用它的 “console” 功能:
[dependencies.web-sys]
version = "0.3"
features = [
"console",
]
为了代码更优雅,我们将把 console.log
函数包装成 println!
形式的宏:
extern crate web_sys;
// 一个 macro(宏) 提供 `println!(..)`-形式 语法,给到 `console.log` 日志功能.
macro_rules! log {
( $( $t:tt )* ) => {
web_sys::console::log_1(&format!( $( $t )* ).into());
}
}
现在,我们可以在 Rust 代码中,调用 log
,开始 console.log
的信息记录。
例如,要记录每个单元(cell)的状态,实时邻居计数,以及下一个状态,我们可以修改 wasm-game-of-life/src/lib.rs
像这样:
diff --git a/src/lib.rs b/src/lib.rs
index f757641..a30e107 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -123,6 +122,14 @@ impl Universe {
let cell = self.cells[idx];
let live_neighbors = self.live_neighbor_count(row, col);
+ log!(
+ "cell[{}, {}] is initially {:?} and has {} live neighbors",
+ row,
+ col,
+ cell,
+ live_neighbors
+ );
+
let next_cell = match (cell, live_neighbors) {
// Rule 1: Any live cell with fewer than two live neighbours
// dies, as if caused by underpopulation.
@@ -140,6 +147,8 @@ impl Universe {
(otherwise, _) => otherwise,
};
+ log!(" it becomes {:?}", next_cell);
+
next[idx] = next_cell;
}
}
在每个 Tick 之间用调试器暂停
例如,我们可用调试器,在我们的 renderLoop
函数每次迭代时,暂停。
只需要在 universe.tick()
之上放置一个 JavaScript 的 debugger;声明 。
const renderLoop = () => {
debugger;
universe.tick();
drawGrid();
drawCells();
requestAnimationFrame(renderLoop);
};
这为我们提供了一个方便的检查点,用于检查记录的消息,并将当前呈现的帧与前一帧进行比较。
练习
- 将日志记录添加到
tick
函数中,该函数记录每个单元格的行和列,这些单元格将状态从 live 转换为 dead,反之亦然。
- 声明一个
panic!()
到Universe::new
方法里面。在 Web 浏览器的 JavaScript 调试器中,检查恐慌的回溯。要做到禁用调试符号,只用不带console_error_panic_hook
可选依赖项,重新构建就好了,并再次检查堆栈跟踪。可以吗?