Async / Await类构造函数 [英] Async/Await Class Constructor

查看:259
本文介绍了Async / Await类构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我正在尝试在类构造函数中使用 async / await 。这样我就可以获得我正在处理的Electron项目的自定义电子邮件标签。

At the moment, I'm attempting to use async/await within a class constructor function. This is so that I can get a custom e-mail tag for an Electron project I'm working on.

customElements.define('e-mail', class extends HTMLElement {
  async constructor() {
    super()

    let uid = this.getAttribute('data-uid')
    let message = await grabUID(uid)

    const shadowRoot = this.attachShadow({mode: 'open'})
    shadowRoot.innerHTML = `
      <div id="email">A random email message has appeared. ${message}</div>
    `
  }
})

然而,目前项目不起作用,出现以下错误:

At the moment however, the project does not work, with the following error:

Class constructor may not be an async method

有没有办法规避这个,以便我可以在其中使用async / await?而不是要求回调或.then()?

Is there a way to circumvent this so that I can use async/await within this? Instead of requiring callbacks or .then()?

推荐答案

这可以从不工作。

async 关键字允许在标记的函数中使用等待 as async 但它也将该函数转换为promise生成器。因此,标有 async 的函数将返回一个promise。另一方面,构造函数返回它正在构造的对象。因此,我们有一种情况,你想要返回一个对象和一个承诺:一个不可能的情况。

The async keyword allows await to be used in a function marked as async but it also converts that function into a promise generator. So a function marked with async will return a promise. A constructor on the other hand returns the object it is constructing. Thus we have a situation where you want to both return an object and a promise: an impossible situation.

你只能使用async / await你可以使用promises,因为他们基本上是承诺的语法糖。你不能在构造函数中使用promises,因为构造函数必须返回要构造的对象,而不是promise。

You can only use async/await where you can use promises because they are essentially syntax sugar for promises. You can't use promises in a constructor because a constructor must return the object to be constructed, not a promise.

有两种设计模式可以解决这个问题,两者都是发明的在承诺到来之前。

There are two design patterns to overcome this, both invented before promises were around.


  1. 使用 init()函数。这有点像jQuery的 .ready()。您创建的对象只能在其自己的 init ready 函数中使用:

  1. Use of an init() function. This works a bit like jQuery's .ready(). The object you create can only be used inside it's own init or ready function:

用法:

var myObj = new myClass();
myObj.init(function() {
    // inside here you can use myObj
});

实施:

class myClass {
    constructor () {

    }

    init (callback) {
        // do something async and call the callback:
        callback.bind(this)();
    }
}


  • 使用构建器。我没有看到这在javascript中使用得太多但是当需要异步构造对象时,这是Java中更常见的解决方法之一。当然,构造需要大量复杂参数的对象时使用构建器模式。这正是异步构建器的用例。区别在于异步构建器不返回对象而是返回该对象的承诺:

  • Use a builder. I've not seen this used much in javascript but this is one of the more common work-arounds in Java when an object needs to be constructed asynchronously. Of course, the builder pattern is used when constructing an object that requires a lot of complicated parameters. Which is exactly the use-case for asynchronous builders. The difference is that an async builder does not return an object but a promise of that object:

    用法:

    myClass.build().then(function(myObj) {
        // myObj is returned by the promise, 
        // not by the constructor
        // or builder
    });
    
    // with async/await:
    
    async function foo () {
        var myObj = await myClass.build();
    }
    

    实施:

    class myClass {
        constructor (async_param) {
            if (typeof async_param === 'undefined') {
                throw new Error('Cannot be called directly');
            }
        }
    
        static build () {
            return doSomeAsyncStuff()
               .then(function(async_result){
                   return new myClass(async_result);
               });
        }
    }
    

    使用async / await执行:

    Implementation with async/await:

    class myClass {
        constructor (async_param) {
            if (typeof async_param === 'undefined') {
                throw new Error('Cannot be called directly');
            }
        }
    
        static async build () {
            var async_result = await doSomeAsyncStuff();
            return new myClass(async_result);
        }
    }
    





  • 注意:虽然在上面的例子中我们使用了异步构建器的promises,但严格来说它们并不是必需的。您可以轻松编写接受回调的构建器。

    Note: although in the examples above we use promises for the async builder they are not strictly speaking necessary. You can just as easily write a builder that accept a callback.






    关于调用的注意事项静态函数中的函数。



    这与异步构造函数无关,但关键字这个实际意味着什么(对于那些来自自动解析方法名称的语言的人来说,这可能有点令人惊讶,也就是说,语言不需要这个关键字)。


    Note on calling functions inside static functions.

    This has nothing whatsoever to do with async constructors but with what the keyword this actually mean (which may be a bit surprising to people coming from languages that do auto-resolution of method names, that is, languages that don't need the this keyword).

    关键字是指实例化的对象。不是班级。因此,你通常不能在静态函数中使用这个,因为静态函数没有绑定到任何对象,而是直接绑定到类。

    The this keyword refers to the instantiated object. Not the class. Therefore you cannot normally use this inside static functions since the static function is not bound to any object but is bound directly to the class.

    也就是说,在以下代码中:

    That is to say, in the following code:

    class A {
        static foo () {}
    }
    

    你做不到:

    var a = new A();
    a.foo() // NOPE!!
    

    您需要将其称为:

    A.foo();
    

    因此,以下代码会导致错误:

    Therefore, the following code would result in an error:

    class A {
        static foo () {
            this.bar(); // you are calling this as static
                        // so bar is undefinned
        }
        bar () {}
    }
    

    要修复它,你可以使 bar 常规函数或静态方法:

    To fix it you can make bar either a regular function or a static method:

    function bar1 () {}
    
    class A {
        static foo () {
            bar1();   // this is OK
            A.bar2(); // this is OK
        }
    
        static bar2 () {}
    }
    

    这篇关于Async / Await类构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆