기본 콘텐츠로 건너뛰기

async function 에 new operator 를 사용하는 방법

tr;dl

  1. async가 필요한 constructor를 만들 때 return (async()=>{ .... })() 로 감싼다.
  2. 사용 시 await new ... 와 같이 new 앞에 await 을 붙여 사용한다.
javascript 에서는 function 을 사용자 정의 객체 타입으로 사용하여 객체 인스턴스를 사용할 수 있게 해주는 new 라는 operator가 있다.

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
이렇게 정의할 경우
var mycar = new Car("Eagle", "Talon TSi", 1993);
mycar와
var kenscar = new Car("Nissan", "300ZX", 1992);
kenscar는 다른 객체를 만들어서 mycar.year, kenscar.year 가 각각 다른 값을 유지할 수 있다.

개인적으로 function을 좋아하기 때문에 React도 hook이 생기고 나선 쓰기 시작했고 깊게 파고 들수록 함수가 가지고 있는 유연함과 강력함에 더더욱 빠져들고 있는데

최근 async/await 비동기 패턴을 자주 쓰면서 async function도 자주 사용하는데
객체 인스턴스를 사용하기 위해 new 를 사용하려고 하면 문제가 있는 것을 발견했다.

가령,
async function foo() {
  let pubInfo = await (await fetch("https://www.cloudflare.com/cdn-cgi/trace")).text();
  return {
    getTrace: ()=> pubInfo
  }
}
이와 같이 async function을 만들고 난 후
bar라는 변수를 new를 가지고 foo객체로 만들려고
let bar = new foo();
하면
Uncaught TypeError: foo is not a constructor 오류가 발생한다.
async 가 붙으면서 function인 foo의 new operator를 사용할 수 없다.

결국 foo 안에서 await 을 사용하려면 어떻게 해야할까?
원하는 것은 결국 constructor 에서 return 으로 반환 받는 { getTrace ... } object를 받으면 되는 것에 집중해보면
function 안의 scope을 전부 (async()=> {.... })() 와 같은 IIFE(Immediately Invoked Function Expression)로 감싸서 반환하면 어떨까?
function foo() {
  return (async ()=>{
    let pubInfo = await (await fetch("https://www.cloudflare.com/cdn-cgi/trace")).text();
    return {
      getTrace: ()=> pubInfo
    }
  })();
}
그러면 foo 는 new 로 instantiate 되면서 (async ()=> {})() block을 실행하면서 Promise 타입을 반환할 것이고
이를 다시 await으로 실행하면 되지 않을까?
new foo();
> Promise {<pending>}
new foo() 했을 때 Promise를 반환한다!
자 그럼 await을 붙여서 풀어보자.
bar = await new foo()
> {getTrace: ƒ}
객체가 달려오는 걸 확인할 수 있다.
따라서 bar.getTrace() 를 실행해보면
bar.getTrace()
> "fl=34f135
h=www.cloudflare.com
ip=....
ts=...
visit_scheme=https
uag=....
colo=ICN
http=http/2
loc=...
tls=TLSv1.3
sni=plaintext
warp=off
"
이와 같이 정상적으로 constructor 를 실행했고 그 내용까지 잘 접근하는 모습을 볼 수 있다.

요약:
  1. async가 필요한 constructor를 만들 때 return (async()=>{ .... })() 로 감싼다.
  2. 사용 시 await new ... 와 같이 new 앞에 await 을 붙여 사용한다.

댓글

이 블로그의 인기 게시물

세상 간단한 https(+secured websocket): Caddy

nginx, apache2 같은 걸로 매번 certbot 연동을 통해 https 하는게 지겨워서 알아보니 Caddy라는게 있더라. 설치법은 강하게 크기 위해 알아서 해본다. # cat /etc/caddy/Caddyfile your.shitty.site:8123 {   proxy / localhost:9123 {     websocket     transparent   } } 이건 외부에서 8123으로 들어오는 걸 내부적으로 9123로 맞춰서 https 맞춰주는 reverse proxy. 만일 port를 생략하면 # cat /etc/caddy/Caddyfile your.shitty.site {   proxy / localhost:9123 {     websocket     transparent   } } 기본포트인 443으로 되어 https://your.shitty.site 로 접속이 된다. 요새 말썽이던 cloudflare 버리고 netlify domain이랑 caddy를 쓰니까 앓던 이가 빠진 느낌. 이 조합은 당분간 계속 써야겠다 싶다.

저지연 오디오 생성 LLVC 사용기

https://github.com/KoeAI/LLVC 써봄 CUDA 11.8 버전 쓰고 있어 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 VC 없어서 설치 https://wikidocs.net/168848 참조 FAIRSEQ 관련 오류 https://github.com/facebookresearch/fairseq/issues/2908 pip install editdistance  설치 No CUDA runtime is found, using CUDA_HOME='C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8' 오류 멀쩡하게 있는데 안됨. pip install torch==2.1.0+cu118 torchvision==0.16.0+cu118 torchaudio==2.1.0+cu118 --extra-index-url https://download.pytorch.org/whl/cu118 다시 설치 set DISTUTILS_USE_SDK=1 이게 문젠가 설정하고 재도전 Using cached ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl (118 kB) Building wheels for collected packages: fairseq   Building wheel for fairseq (pyproject.toml) ... error   error: subprocess-exited-with-error   × Building wheel for fairseq (pyproject.toml) did not run successfully.   │ exit code: 1   ╰─> [1829 lines of output]       No CUDA runtime is found, usi...