Asynchronous JavaScript ES6类是否可用于异步代码库?

Asynchronous JavaScript ES6类是否可用于异步代码库?,asynchronous,ecmascript-6,es6-promise,es6-class,Asynchronous,Ecmascript 6,Es6 Promise,Es6 Class,作为一种组织模式,异步代码可以提供什么。下面是一个ES7 async/await示例,ES6类是否可以在ES7中具有异步方法或构造函数 我可以做: class Foo { async constructor() { let res = await getHTML(); this.res = res } } 如果不是的话,构造函数应该如何工作呢 class Foo { constructor() { getHTML().th

作为一种组织模式,异步代码可以提供什么。下面是一个ES7 async/await示例,ES6类是否可以在ES7中具有异步方法或构造函数

我可以做:

class Foo {
    async constructor() {
        let res = await getHTML();
        this.res = res
    }
}
如果不是的话,构造函数应该如何工作呢

class Foo {
    constructor() {
        getHTML().then( function (res) {
            this.res = res
        }
    }
}
如果这两种模式都不起作用,ES6
类中的构造函数(以及类)能否支持对对象状态进行操作的任何形式的异步性?或者,它们只是用于纯粹的同步代码库吗?上面的示例在构造函数中,但它们不需要是。。把问题再往下推一层

class Foo {
    myMethod () {
      /* Can I do anything async here */
    }
}
或者,用一个getter

class Foo {
    get myProp() {
        /* Is there any case that this is usefully asynchronous */
    }
}
我能想到的唯一例子是在同一个方法/构造函数/getter中并行运行某些东西,但在得出结论之前要解决整个问题。我只是感到困惑,因为它似乎推动了完全异步库的发展,这只会让事情变得混乱。除了课本上的例子,我找不到一个它们有用的应用程序

我可以做
异步构造函数()


不,这是一个语法错误-就像
constructor*()
一样。构造函数是一种不返回任何内容(无承诺、无生成器)的方法,它只初始化实例

如果不是的话,构造函数应该如何工作呢

这样的构造函数根本不应该存在,请参见

ES6类可以支持对对象状态进行操作的任何形式的异步吗?或者,它们只是用于纯粹的同步代码库吗

是的,您可以在类上使用异步方法(即使使用建议的
async
语法),getter也可以返回承诺


但是,您需要决定在某个异步进程仍处于活动状态时调用某个方法时应该发生什么。如果您想让它对您的所有操作进行排序,那么您应该将实例的状态存储在一个承诺中,以便您可以链接到该序列的末尾。或者,如果您希望允许并行操作,最好的方法是使您的实例不可变,并为另一个实例返回承诺。

类在安排异步任务时有用的另一种方法是独占使用


当然,这与创建一个简单的对象文本或一个新文件并包含它没有什么不同,只是您可以更干净地扩展它。

ECMAScript 2017旨在成为异步方法的类

调用另一个异步或承诺返回函数是一个简单的过程

无论延迟执行如何,高表达性代码都会从上而下无中断地读取

若您有回调、替代错误处理程序、并行执行或其他未满足的需求,请在函数体中实例化承诺。最好将代码放在函数体中,而不是放在承诺执行器中,并且注意没有try-catch包装回调代码:在那里几乎什么都不做

异步方法可以返回承诺、常规值或抛出

Node.js人们过去喜欢的回调API,现在我们会满怀激情地憎恨:它们都必须用承诺来包装

async/await的美妙之处在于错误会隐式出现

class MyClass {
  async doEverything() {
    const sumOfItAll = await http.scrapeTheInternet() +
      await new Promise((resolve, reject) =>
        http.asyncCallback((e, result) => !e ? resolve(result) : reject(e)))
    return this.resp = sumOfItAll
  }
}
如果限制为ECMAScript 2015且无异步,则返回承诺值:

class ES2015 {
  fetch(url) {
    return new Promise((resolve, reject) =>
      http.get(url, resolve).on('error', reject))
      .then(resp => this.resp = resp) // plain ECMAScript stores result
      .catch(e => { // optional internal error handler
        console.error(e.message)
        throw e // if errors should propagate
      })
  }
}
这个ECMAScript 2015版本是您真正想要了解的,任何想要的行为都可以使用返回的promise构造进行编码

如果您真的非常想在构造函数中执行承诺,那么最好传入然后捕获函数,或者提供一些回调构造,以便消费者可以对承诺的履行或拒绝采取行动。在构造函数中,等待nextTick/,然后再进行实际工作也是一种很好的做法


每个承诺都需要一个最终的捕获,否则会有麻烦

这是一个延迟响应,但第二个示例不起作用的原因是上下文错误。当您将
函数(){}
作为参数传递给
Promise.prototype.then()
时,函数中的词法
this
将是函数本身,而不是类。这就是设置
This.res
似乎不起作用的原因:
This
,在这种情况下,指的是函数自身的范围

在Javascript中有几种访问外部作用域的方法,经典的方法(您在ES5代码中可以看到很多)是:

通过引用类
this
,您可以在内部作用域中访问它

ES6的方法是使用,它不会创建新的作用域,而是“保留”当前的作用域

class Foo {
  constructor() {
    getHTML().then(res => this.res = res)
  }
}
除了上下文方面的考虑,我认为这仍然不是一个最佳的异步模式,因为您无法知道
getHTML()
何时完成,或者更糟糕的是,何时失败。这个问题用一个简单的方法优雅地解决了。虽然不能创建
异步构造函数(){…}
,但可以在构造函数中启动承诺,并在依赖它的函数中等待它


类构造函数中的异步属性。

你可以从与实例解析的构造函数返回一个承诺,这样你就可以在实例初始化后访问它。@KevinB我确实想到了这个想法,但听起来很可怕。我也不是特别喜欢它,但是。。。还有别的办法吗?必须在某个地方有一个回调,它要么是一个承诺,要么是一个作为参数传递的回调。async/await仍然有一个回调,你只是看不到而已。@KevinB我认为你是对的,我认为类很快就会成为反模式。使用非同步代码库进入它们将非常困难,从它们中编写真正有用的异步库将非常困难,而且从调用方的角度来看,编写
wait new Foo(url)将非常困难我已经把问题扩大了,而且
class Foo {
  constructor() {
    var _this = this

    getHTML().then(function (res) {
      _this.res = res
    })
  }
}
class Foo {
  constructor() {
    getHTML().then(res => this.res = res)
  }
}