我有一个针对动漫(8到10岁)的JavaScript编码课程的原型。教学脚本允许其用户像
一样进行同步编程draw(something);
wait(some time);
draw(something_else);
同步编程看起来比常规的JavaScript技术友好得多,但是在后台是异步/等待的,并且不会使浏览器停滞不前。
您可以在http://codepegs.com/上尝试其工作原理,并在http://codepegs.com/cphelp.html上找到说明(滚动至定时功能)。
异步/等待非常有约束力。还有很多事情可以做,但是在重构系统之前,让我问一下,您是否知道可以使用JavaScript进行伪同步编程的现有解决方案?
我试图进行搜索,但答案似乎无济于事。这就是为什么我链接了一个示例。
PS:抱歉,我必须添加一个脚本。我要求提出一个更详细的实施方案。原则上,它是在一年前完成的。它很粗糙,但是有效。我不喜欢它有很多原因,但是我决定在开始新一轮编程之前先询问一下。
看,在脚本(或咒语)完成(异步)运行之后,它会留下按这种方式或另一种方式按时执行的功能序列。这样的列表可以完成很多事情。假设您想取消某些挂起的函数,或者想重复它们,也许更改某些东西,等等。这种伪同步模型并不是非常复杂,但并不是那么简单。想象一下,您想要一个无限的动画(已经实现,但是笨拙),等等。
答案 0 :(得分:1)
没有可靠的方法来同步在前端JS中进行I / O。有同步的AJAX,但是WebWorkers,setTimeout,WebSockets等始终是异步的。
因此,您需要async/await
才能获得同步样式的编码模式。
还有另一种方法,您基本上可以创建一个Promise队列:
enqueue(function foo(){}); // put on the queue
enqueue(function bar(){}); // put on the queue
enqueue(function baz(){}); // put on the queue
这意味着如果队列一次只处理一个函数调用,则foo,bar和baz将按顺序运行。但是,没有库就没有简单的方法可以将一个函数的结果传递给下一个函数。那就是承诺或异步库的用途。
要了解队列方法的工作原理,请查看以下库:
答案 1 :(得分:1)
按照Bergi的建议,以同步方式实际运行代码并将所有更改推送到队列中可能会更优雅,然后您可以缓慢地重放更改:
const queue = [];
function draw(text) { queue.push({command: "draw", value: text }); }
function wait(value) { queue.push({ command: "delay", value }); }
async function end() {
for(const { command, value } of queue) {
switch(command) {
case "draw":
console.log(value);
break;
case "delay":
await new Promise(res => setTimeout(res, value));
break;
}
}
}
// Your code:
draw("And you get...");
wait(1000);
draw("nothing :/");
end();
答案 2 :(得分:0)
万一其他失败,您仍然可以使用JavaScript本身编写自己的JavaScript转译器:
您可以使代码很有希望,然后只需将程序转换为使用async / await:
function execute(context, code) {
let result = "";
for(const line of code.split("\n"))) {
if(["if", "else", "var", "for", "while"].some(keyword => line.includes(keyword)) {
result += line + "\n";
} else {
result += "await " + line + "\n";
}
}
with(context) {
return eval(`(async function() { ${result} })()`);
}
}
然后将用户代码传递给执行:
execute({
async draw() { /*...*/ },
async wait(ms) { await new Promise(res => setTimeout(res, ms)); },
},
`draw(something);
wait(some time);
draw(something_else);`
);
那只是为了给您一个基本的想法,但是it works quite well。
或者另一种方法可能是建立一个迭代器,使您可以逐行浏览代码:
let continuation = Promise.resolve();
function wait(ms) { continuation = new Promise(resolve => setTimeout(resolve, ms)); }
function draw() { /*...*/ }
function execute( code) {
const iterator = eval("(function* () {" + code.split("\n").join("\nyield;\n") + "})();");
function next() {
const { value, done } = iterator.next();
if(done) return;
continuation.then(next);
}
}
execute(`
console.log("wait a second....");
wait(1000);
console.log("done!");
`);
works也是如此,我想它实际上是一个很好的工作方式,只有在代码包含多行字符串/函数的情况下,它才会失败。