【问题标题】:Programmatically convert synchronous code to asynchronous code以编程方式将同步代码转换为异步代码
【发布时间】:2015-02-24 17:30:13
【问题描述】:

我正在为要在浏览器中运行的元语言编写解析器。元语言是阻塞的,但由于javascript的限制,需要在解释器中转换为非阻塞。

例如,元语言代码可能看起来像

1. dosomething(4)
2. dosomethingelse(1)
3. dosomething(7)
4. goto 2

在javascript中实现的功能为

function dosomething(n, callback) {
  ... // do something with n
  setTimeout(callback, 1000);
}

function dosomethingelse(n, callback) {
  ... // do something else with n
  setTimeout(callback, 1000);
}

如果没有goto 语句,这将很容易编译为javascript,然后编译为eval。但是,我不知道如何实现gotos。任何帮助表示赞赏。

【问题讨论】:

  • 无条件跳转只是一个while循环
  • 如何解释非阻塞语言中的阻塞 while 循环?
  • 我不明白这个问题。
  • 您是否要等待所有异步 dosomething 调用完成然后执行 goto?
  • 我通常使用 Promise 来实现。喜欢github.com/kriskowal/q

标签: javascript interpreter metalanguage


【解决方案1】:

正如其他人所说,请查看 Promises。本教程确实帮助我开始使用它们,希望它也可以帮助你。 https://spring.io/understanding/javascript-promises

【讨论】:

    【解决方案2】:

    使用yield 创建可以暂停的函数,然后使用regenerator 在旧版浏览器中运行它:

    首先,我们将您的语言中的dosomething(4) 转换为:

    function doSomething(n, callback){
        setTimeout(function(){ callback(null,true); }, n);
    }
    

    注意节点错误返回约定 - 回调有两个参数 - 第一个是错误,第二个是返回值。

    然后 - 您可以轻松地将它们转换为 Promise:

    var doSomething = Promise.promisify(doSomething); // using bluebird.
    

    现在,当他们返回承诺时,您可以使用 yields 换行:

    Promise.coroutine(function*(){ 
        yield dosomething(4);
        yield dosomethingelse(1);
        yield dosomething(7);
    });
    

    您需要调用addYieldHandler 来处理产生的非承诺值。这将“同步”执行它们,等待每个 Promise 在开始下一个 Promise 之前解决。最后使用 regenerator 将你的代码转换成 ES5 浏览器可以运行的东西(因为 yield 只在 FF 和 Chrome 中的标志 atm 下工作)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 2017-05-19
      • 2018-09-04
      • 2015-04-15
      相关资源
      最近更新 更多