【问题标题】:Async/await in web browser or in node.js?Web 浏览器或 node.js 中的异步/等待?
【发布时间】:2018-12-12 01:44:01
【问题描述】:

是否有任何尝试将 C# 5.0 中的 async/await 功能引入任何可以编译为 JavaScript 的语言(例如 CoffeScript)? (所以它可以在 web 浏览器或 node.js 中使用。)

【问题讨论】:

  • 浏览器内 JavaScript 和通过 node.js 编写的 JavaScript 有自己的异步编程方式。最好简单地了解它的工作原理并按预期使用它,而不是试图将其强制转换为不同的模型(无论如何这可能是完全不可能的)。
  • @Pointy:C# 5 的等待是围绕相同回调模型的语法包装器。在任何语言中,它们都比回调更容易使用。
  • 好吧,我当然要听从你更广泛的经验 :-)
  • @Pointy 这不是真的——浏览器中的 JS 和 NodeJS 上的 JS 从根本上具有 相同 编程模型,那就是事件循环加上诸如 setTimeout、事件之类的基本原理, 和回调。碰巧很多(但不是全部)NodeJS 的异步函数使用回调,而在浏览器中它更多的是事件。但这只是统计数据和风格的问题。
  • @flow 我并不是说浏览器和 Node 中的 JavaScript 有自己的 distinct 异步模型;我列出了这两个环境,因为还有其他环境(尤其是 Rhino)有 同步 I/O(等)操作。

标签: javascript async-await


【解决方案1】:

Async 在 JavaScript 和谐功能列表中。到目前为止,已经有很多尝试在浏览器或节点中提供此类功能,但似乎没有一个与 Harmony Proposal 兼容:

  • 可以使用 JS1.7 生成器模拟异步(请参阅task.js)。 V8 (without experimental mode) 尚不支持开箱即用,但可在 FF 中使用。可能traceurMasacra 编译器可用于将生成器带入其他环境。
  • node-fibers 库为节点中的异步编程提供了其他机制(尽管会降低性能)。描述了基于 v8cgi 的其他尝试here
  • Rhino 有开箱即用的continuations,提供了很好的选择。这就是为什么 Ringo.js 可能值得一看。
  • 很少有基于 js2js 翻译的解决方案可用,例如:jscxNarrativeJSjwacsStratifiedJS。一些支持与节点的集成。
  • 有许多 Promise/Future 库试图在不扩展语法的情况下解决回调问题,但是它们都存在可组合性问题,即不能在回调之间使用循环等语言结构。

【讨论】:

    【解决方案2】:

    async/await 看起来是 coming in ECMAScript 7。此proposal 已于 2014 年 1 月进入规范流程的第一阶段。

    好消息是 Google 的 traceur compiler 已经支持它,所以你今天就可以开始使用它了。

    示例语法:

    async function asyncValue(value) {
      await timeout(50);
      return value;
    }
    

    async/await 也在TypeScript roadmap

    【讨论】:

    【解决方案3】:

    我不熟悉 C#,但听起来你正在寻找的是某种延续,所以不是写

    fs.readFile 'foo.txt', (err, data) ->
      myFunc data
    

    你可以写一些类似的东西

    data = &fs.readFile 'foo.txt'  # not a real syntax
    myFunc data
    

    这不是 JavaScript 或 CoffeeScript 提供的。但是,还有其他几个编译器可以做这样的事情:

    • TameJS - 基于 JavaScript,主要只是添加了这个功能
    • Kaffeine - 基于 JavaScript,增加了一堆特性
    • coco - 基于 CoffeeScript

    另请参阅:CoffeeScript wiki 上的 List of languages that compile to JavaScript

    【讨论】:

    • 在 Coco wiki 上查找“backcall”。它使用<- 运算符。
    • 我可以提一下,将这样的语法添加到 javascript 中会带来一整套负面影响,例如必须信任已编译的代码、必须了解已编译的代码、必须调试已编译的代码以及试图在异步环境中滥用同步设计模式。基本上它们是很容易泄漏的抽象,除非您确切知道自己在做什么,而且我相信只有模块作者和少数人确切知道他们在做什么
    【解决方案4】:

    是的,你甚至不需要编译它,因为它只是一个简单的 JavaScript 库。

    我的一个名为sharpnr.js 的项目旨在使用C#(当然还有.NET)的强大功能来扩展JavaScript,例如await/async 或LINQ。

    该库目前处于测试阶段,但它很稳定,几乎支持所有语句(例如循环、switch、if),并且可以与现有库(如 jQuery)很好地配合使用。

    await/async 语法几乎与 C# 版本相同:

    var getAsync = async(function(url) {
      var result = await; $.get(url);
      $("#test").html(result);
    });
    getAsync("http://www.sharpnrjs.com");
    

    jsfiddle 上的工作示例。

    您可以从github下载该库。

    【讨论】:

      【解决方案5】:

      当节点 0.11 (with v8 3.19 [1], which has generators[2]) 到达时,您可以使用Galaxy 和如下代码。

      但是,只是在一个标志的后面。他们是supported natively in ioJS

      function* countLines(path) {
          var names = yield fs.readdir(path);
          var total = 0;
          for (var i = 0; i < names.length; i++) {
              var fullname = path + '/' + names[i];
              if ((yield fs.stat(fullname)).isDirectory()) {
                  total += yield countLines(fullname);
              } else {
                  var count = (yield fs.readFile(fullname, 'utf8')).split('\n').length;
                  console.log(fullname + ': ' + count);
                  total += count;
              }
          }
          return total;
      }
      
      function* projectLineCounts() {
          var total = 0;
          total += yield countLines(__dirname + '/../examples');
          total += yield countLines(__dirname + '/../lib');
          total += yield countLines(__dirname + '/../test');
          console.log('TOTAL: ' + total);
          return total;
      }
      

      【讨论】:

      • +1 谢谢,用于 node.js 中的解决方案,希望是现代浏览器:)
      【解决方案6】:

      您可以在启用了 Experimental JS 标志的 Google Chrome 中使用内置生成器、Promises 和一个小的 spawn() function by Jake Archibald 来实现异步/等待:

      spawn(function*() { //this function is async
            let story = yield getJSON('story.json'); //yield is like await
            addHtmlToPage(story.heading);
      });
      

      或者,您可以使用:

      对于不支持 ES6 的浏览器,有Facebook Regenerator

      【讨论】:

        【解决方案7】:

        好消息

        nodejs 从 v7.0.0 开始支持它(嗯,部分支持),仍然需要一个和谐标志 --harmony_async_await,显然有一些错误,包括内存泄漏,对于 more details,但也有一些问题,以及一位评论员advises 等到 v8 版本 55,这可能不会太久。

        【讨论】:

          【解决方案8】:

          为了完整性:我发现Saltarelle Compiler(实际上将 C# 编译为 JavaScript)也支持 await/async。

          【讨论】:

            【解决方案9】:

            如果你对 JavaScript 的 .NET 风格的异步编程感兴趣,你应该研究一下 Rx for JavaScript。 Rx for JavaScrpt 是 Microsoft 的响应式框架的 JavaScript 端口。反应式框架描述为:

            一个用于编写异步和基于事件的程序的库,使用 可观察的集合和 LINQ 样式的查询运算符。

            您可以下载 Rx for JavaScript here

            您可以阅读更多相关信息,包括示例here

            你也可以用 npm 安装到 node 上:

            npm install rx

            它适用于 jQuery 等库,但我不是 CoffeeScript 程序员,所以我不确定与该语言中的其他 JavaScript 库的互操作性有什么支持。

            【讨论】:

            • Rx for JavaScript 是否提供异步/等待功能?
            【解决方案10】:

            Javascript 在 ECMA 7 中提供了 async-await 功能。现在所有的异步函数都可以通过 Promise 并等待 Promise 解决来等待。大多数异步函数,如 DB 调用、API 调用、fs 和事件现在都在 Javascript 和 nodeJs 中返回 Promise。现在使用 async-await 代码更清晰、更易于理解和调试。

            例子

            function timeout(){
              return new Promise( resolve => {
                setTimeout(function(){
                  resolve(true);
                }, 5000);
              });
            }
            
            async function f(){
                let result = await timeout();
            }
            

            【讨论】:

              【解决方案11】:

              https://github.com/loveencounterflow/coffy-script 尝试将 yield 添加到 CoffeeScript。 CoffyScript 是非常 新的,在我写这篇文章时,我正在思考require.extensions 是一个全球性的所带来的困难,以及我是否应该成为一个单独的扩展。也就是说,CoffyScript 确实有效,您会在我的 github 页面上找到许多示例,这些示例展示了如何使用 suspendresumeyield 编写非常简洁的异步代码。

              鉴于yield 已经到了 NodeJS 11.2,我相信我们应该研究如何使用生成器/协程来使异步编程更容易接受。我已经放弃了承诺,与他们的经历并不那么愉快。再说一次,yield 可能需要一段时间才能在所有主流浏览器中可用。

              【讨论】:

                猜你喜欢
                • 2021-03-26
                • 1970-01-01
                • 2017-08-04
                • 2014-02-15
                • 1970-01-01
                • 2019-04-22
                • 2019-01-15
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多