UFO ET IT

JavaScript ES6 클래스가 비동기 코드베이스와 함께 사용됩니까?

ufoet 2021. 1. 8. 20:56
반응형

JavaScript ES6 클래스가 비동기 코드베이스와 함께 사용됩니까?


ES6 클래스 는 조직의 패턴으로 비동기 코드에 무엇을 제공 할 수 있습니까 ? 아래는 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가 객체의 상태에서 작동하는 모든 형태의 비동기 성을 지원할 수 있습니까? 아니면 순전히 동기식 코드베이스에만 해당합니까? 위의 예제는 생성자에 있지만 그럴 필요는 없습니다. 문제를 한 단계 더 아래로 밀어 넣습니다.

class Foo {
    myMethod () {
      /* Can I do anything async here */
    }
}

또는 게터로 ...

class Foo {
    get myProp() {
        /* Is there any case that this is usefully asynchronous */
    }
}

내가 생각할 수있는 유일한 예는 동일한 메서드 / 생성자 / 게터 내에서 무언가를 병렬로 실행하지만 결론 전에 모든 것을 해결하는 것입니다. 완전히 비동기식 라이브러리에 대한 모든 푸시로 보이므로 혼란스러워합니다. 교과서 예제를 제외하고는 유용한 응용 프로그램을 찾을 수 없습니다.


할 수 있습니까 async constructor()

아니요, 구문 오류 constructor* ()입니다.. 생성자는 아무것도 반환하지 않는 (약속 없음, 생성기 없음) 메서드이며 인스턴스를 초기화 할뿐입니다.

그리고 그렇지 않다면 생성자가 어떻게 작동해야합니까?

그러한 생성자는 전혀 존재하지 않아야합니다 . 생성자 함수가 Promise를 반환하도록하는 것은 나쁜 습관입니까?를 참조하십시오 .

ES6 클래스는 객체의 상태에서 작동하는 모든 형태의 비동기를 지원할 수 있습니까? 아니면 순전히 동기식 코드베이스에만 해당합니까?

예, async클래스에서 비동기 메서드 (제안 된 구문을 사용하더라도 )를 사용할 수 있으며 게터는 promise를 반환 할 수도 있습니다.

그러나 일부 비동기 프로세스가 여전히 활성 상태 인 동안 메서드가 호출되면 어떤 일이 발생해야하는지 결정해야합니다. 모든 작업의 ​​순서를 지정하려면 연결할 수있는 해당 순서의 끝에 대한 약속 안에 인스턴스의 상태를 저장해야합니다. 또는 병렬 작업을 허용하려는 경우 가장 좋은 방법은 인스턴스를 변경 불가능하게 만들고 다른 인스턴스에 대한 약속을 반환하는 것입니다.


클래스가 비동기 작업을 배열하는 데 유용 할 수있는 또 다른 방법은 정적 메서드를 배타적으로 사용하는 것입니다 .

class Organizer {
    static async foo() {
        const data = await this.bar();
        data.key = value;
        return data;
    }
    static async bar() {
        return {foo:1, bar:2}
    }
};

Organizer.foo();

물론 이것은 단순한 객체 리터럴이나 새 파일을 만들고 포함하는 것과 다르지 않습니다. 단, 더 깔끔하게 할 수 있다는 점이 다릅니다 extend.


ECMAScript 2017은 비동기 메서드의 클래스입니다.

다른 비동기 또는 약속 반환 함수를 호출하는 것은 한 줄입니다!

표현력이 뛰어난 코드는 지연된 실행에 관계없이 중단없이 위에서 아래로 읽습니다.

콜백, 대체 오류 처리기, 병렬 실행 또는 기타 충족되지 않은 요구 사항이있는 경우 함수 본문에서 약속을 인스턴스화합니다. promise 실행기보다는 함수 본문에 코드를 포함하는 것이 더 낫습니다. 그리고 try-catch 래핑 콜백 코드가 없다는 점에 유의하십시오. 거기에서 아무것도하지 마십시오.

The async method can return a promise, a regular value, or throw

The callback apis that Node.js people used to love, we will now hate with a passion: they must all be wrapped in promises

The beauty of async/await is that errors bubble up implicitly

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
  }
}

If limited to ECMAScript 2015 and no async, return promise values:

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
      })
  }
}

This ECMAScript 2015 version is what you are really asking about, any desired behavior can be coded up using the returned promise construct.

If you really, really want to execute promises in the constructor, it is a good idea to pass in then-catch functions or provide some callback construct so that consumers can take action on promise fulfillment or rejection. In the constructor, it is also good practice to wait for nextTick/.then before doing real work.

Every promise needs a final catch or there will be trouble


This is a late response, but the reason your second example doesn't work is because of a context error. When you pass a function () {} as an argument to Promise.prototype.then(), the lexical this inside the function will be the function itself, and not the class. This is why setting this.res seems to do nothing: this, in that case, refers to the function's own scope.

There are several ways of accessing an outer scope in Javascript, the classic one (that you see abundantly in ES5 code) being:

class Foo {
  constructor() {
    var _this = this

    getHTML().then(function (res) {
      _this.res = res
    })
  }
}

By making a reference to the class this, you can access it in inner scopes.

The ES6 way of doing it is to use arrow functions, which do not create a new scope, but rather "keep" the current one.

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

Aside from context concerns, this is still not an optimal asynchronous pattern in my opinion, because you've got no way to know when getHTML() has finished, or worse, has failed. This problem is solved elegantly with async functions. Though you cannot make an async constructor () { ... }, you can initiate a promise in the constructor, and await it in the functions that depend on it.

Example gist of an async property in a class constructor.

ReferenceURL : https://stackoverflow.com/questions/37556058/are-javascript-es6-classes-of-any-use-with-asynchronous-code-bases

반응형