我在做什么
我正在使用 Blockly 构建海龟图形应用程序。用户可以从 block 构建代码,然后 Blockly 引擎生成 JS 代码,绘制到 Canvas 上。
我的问题是什么
Blockly 引擎生成 JS 代码,但将其作为字符串返回,我必须通过 eval()
将其绘制到 Canvas 上。
我可以更改 block 的代码以生成不同的输出,但保持它尽可能简单很重要,因为用户可以阅读 block 输入背后的实际代码。所以我不想把它搞砸。
我想做什么
我可以完全控制原子操作(go
、turn
等),所以我想在开头插入一小段代码函数,这会延迟其余函数体的执行。像这样的东西:
function go(dir, dist) {
// wait here a little
// do the drawing
}
我认为它应该是同步的,它可以在执行流程中保持延迟。我尝试使用 setTimeout
(异步,失败)、promise
(失败)、循环中的时间戳检查(失败)。
在 JS 中甚至可能吗?
最佳答案
您不能让代码同步等待。您唯一会得到的是一个卡住的浏览器窗口。
您需要的是使用 js interpreter而不是评估。通过这种方式,您可以暂停执行、播放动画、突出显示当前正在执行的 block 等……教程中有许多示例可以帮助您入门。这是一个工作代码,基于 JS interpreter example :
var workspace = Blockly.inject("editor-div", {
toolbox: document.getElementById('toolbox')
});
Blockly.JavaScript.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
Blockly.JavaScript.addReservedWords('highlightBlock');
Blockly.JavaScript['text_print'] = function(block) {
var argument0 = Blockly.JavaScript.valueToCode(
block, 'TEXT',
Blockly.JavaScript.ORDER_FUNCTION_CALL
) || '\'\'';
return "print(" + argument0 + ');\n';
};
function run() {
var code = Blockly.JavaScript.workspaceToCode(workspace);
var running = false;
workspace.traceOn(true);
workspace.highlightBlock(null);
var lastBlockToHighlight = null;
var myInterpreter = new Interpreter(code, (interpreter, scope) => {
interpreter.setProperty(
scope, 'highlightBlock',
interpreter.createNativeFunction(id => {
id = id ? id.toString() : '';
running = false;
workspace.highlightBlock(lastBlockToHighlight);
lastBlockToHighlight = id;
})
);
interpreter.setProperty(
scope, 'print',
interpreter.createNativeFunction(val => {
val = val ? val.toString() : '';
console.log(val);
})
);
});
var intervalId = setInterval(() => {
running = true;
while (running) {
if (!myInterpreter.step()) {
workspace.highlightBlock(lastBlockToHighlight);
clearInterval(intervalId);
return;
}
}
}, 500);
}
#editor-div {
width: 500px;
height: 150px;
}
<script src="https://rawgit.com/google/blockly/master/blockly_compressed.js"></script>
<script src="https://rawgit.com/google/blockly/master/blocks_compressed.js"></script>
<script src="https://rawgit.com/google/blockly/master/javascript_compressed.js"></script>
<script src="https://rawgit.com/google/blockly/master/msg/js/en.js"></script>
<script src="https://rawgit.com/NeilFraser/JS-Interpreter/master/acorn_interpreter.js"></script>
<xml id="toolbox" style="display: none">
<block type="text"></block>
<block type="text_print"></block>
<block type="controls_repeat_ext"></block>
<block type="math_number"></block>
</xml>
<div>
<button id="run-code" onclick="run()">run</button>
</div>
<div id="editor-div"></div>
编辑
添加了变量running
来控制解释器。现在它会跳过,直到 running
变量设置为 false,因此 highlightBlock 函数内的 running = false
语句实际上用作断点。
编辑
引入了lastBlockToHighlight
变量来延迟突出显示,因此突出显示最新的运行语句,而不是下一个。遗憾的是,JavaScript 代码生成器没有类似于 STATEMENT_PREFIX
的 STATEMENT_SUFFIX
配置。
关于javascript - JS 在生成的函数中等待/暂停,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39069363/