async-constructor

The helper functions for creating classes that require asynchronous constructors.

Usage no npm install needed!

<script type="module">
  import asyncConstructor from 'https://cdn.skypack.dev/async-constructor';
</script>

README

async-constructor npm GitHub license

The helper functions for creating classes that require async constructors.

Install

npm install --save async-constructor
# or
yarn add async-constructor

Usage

This module is created for TypeScript, but can also be used in JavaScript.

JavaScript

You may not need the module because JavaScript constructor could return a Promise<this>:

class Resource {
  constructor(url) {
    return (async () => {
      this.content = await load(url)
      return this
    })()
  }
}

or

function Resource(url) {
  return (async () => {
    this.content = await load(url)
    return this
  })()
}

TypeScript

AsyncConstructor

ES2017
import { AsyncConstructor } from 'async-constructor'

class Resource extends AsyncConstructor {
  content!: string

  constructor(url: string) {
    super(async () => {
      this.content = await load(url)
    })
  }
}

const resource = await new Resource('data.txt')
ES2015
import { AsyncConstructor } from 'async-constructor/lib/es2015'

class Resource extends AsyncConstructor {
  content!: any

  constructor(url: string) {
    super(async function(this: Resource) {
      this.content = await load(url)
    })
  }
}

;(async () => {
  const resource = await new Resource('data.txt')
})()

appendAsyncConstructor

function appendAsyncConstructor<T, U extends any[]>(
  target: T
, asyncConstructor: (...args: U) => PromiseLike<void>
, args?: U
): void

Once a class has an async constructor, its subclasses will also have async constructors.

The function AsyncConstructor is a wrapper for appendAsyncConstructor, you can call appendAsyncConstructor in the sync constructor to append an async constructor.

import { appendAsyncConstructor } from 'async-constructor'

class Resource {
  content!: string

  constructor(url: string) {
    appendAsyncConstructor(this, async () => {
      this.content = await load(url)
    })
  }
}

class DataResource extends Resource {
  constructor(append: string) {
    super('data.txt')

    appendAsyncConstructor(this, async () => {
      this.content += append
    })
  }
}

const resource = await new DataResource('\n')

The multiple async constructors will be called in order, and always called after all sync constructor.

mixinAsyncConstructor

function mixinAsyncConstructor<Base extends Constructor>(
  base: Base
, asyncConstructor: (...args: ConstructorParameters<Base>) => PromiseLike<void>
): new (...args: ConstructorParameters<Base>) => PromiseLike<ReturnTypeOfConstructor<Base>>

The mixin function mixinAsyncConstructor is also used to add async constructors to classes, but you cannot access protected/private member in the async constructor.

import { mixinAsyncConstructor } from 'async-constructor'

class Base {
  content!: string
  constructor(url: string) {}
}

const Resource = mixinAsyncConstructor(Base , async function(this: Base, url) {
  this.content = await load(url)
})

const resource = await new Resource('data.txt')