Дизайн класса с учетом метода кеширования - PullRequest
0 голосов
/ 08 апреля 2020

Я рассчитываю на разработку классов таким образом, чтобы у меня были небольшие методы функций. Например, если у меня есть fullPath, я бы хотел изолировать это от функции и иметь возможность использовать это значение в других методах. Геттеры кажутся очевидным решением этой проблемы, однако я хотел бы также иметь поддержку asyn c / обещание. Например, метод content, если я хочу использовать возвращаемое значение из content в других методах, я не хочу повторного запуска функции. Один из способов обойти это состоит в том, чтобы «кэшировать» его в приватном значении, поэтому при его повторном запуске вы все равно можете вызывать его по всему коду как await this.contents.

  _contents: string | null = null
  async contents() {
    if (this._contents) return this._contents
    this._contents = await readFile(this.fullPath(), { encoding: 'utf8' })
    return this._contents
  }

Вот пример передачи переменные из одного метода в другой метод. Основным недостатком этого является то, что вам нужно сохранить значение переменной и передать их.

import * as fs from 'fs'
import * as nodePath from 'path'
import * as util from 'util'
const readFile = util.promisify(fs.readFile)

class FileLoader {
  constructor(private readonly options: {
    cwd: string
    path: string
  }) { }

  fullPath() {
    const { path, cwd } = this.options
    return nodePath.isAbsolute(path) ? path : nodePath.join(cwd, path)
  }

  extention() { 
    const { path } = this.options
    return nodePath.extname(path)
  }

  async contents(fullPath: string) {
    return readFile(fullPath, { encoding: 'utf8' })
  }

  async main() {
    const fullPath = this.fullPath()
    const extension = this.extention()
    const contents = await this.contents(fullPath)
    return {
      ...this.options,
      fullPath,
      extension,
      contents
    }
  }

}

const file = new FileLoader({ cwd: './', path: 'README.md' })

file.main().then(console.log)

Вот версия с примером кэширования, использованным выше, это позволяет повторно запускать функции без выполнение значений каждый раз.

import * as fs from 'fs'
import * as nodePath from 'path'
import * as util from 'util'
const readFile = util.promisify(fs.readFile)

class FileLoader {
  constructor(private readonly options: {
    cwd: string
    path: string
  }) { }

  _fullPath: string | null = null
  fullPath() {
    if (this._fullPath) return this._fullPath
    const { path, cwd } = this.options
    this._fullPath = nodePath.isAbsolute(path) ? path : nodePath.join(cwd, path)
    return this._fullPath
  }

  _extention: string | null = null
  extention() { 
    if (this._extention) return this._extention
    const { path } = this.options
    this._extention = nodePath.extname(path)
    return this._extention
  }

  _contents: string | null = null
  async contents() {
    if (this._contents) return this._contents
    this._contents = await readFile(this.fullPath(), { encoding: 'utf8' })
    return this._contents
  }

  async main() { 
    return {
      ...this.options,
      fullPath: this.fullPath(),
      extention: this.extention(),
      contents: await this.contents(),
    }
  }
}

const file = new FileLoader({ cwd: './', path: 'README.md' })

file.main().then(console.log)

Вот некэшированная версия с getter / setter.

import * as fs from 'fs'
import * as nodePath from 'path'
import * as util from 'util'
const readFile = util.promisify(fs.readFile)

class FileLoader {
  constructor(private readonly options: {
    cwd: string
    path: string
  }) { }

  get fullPath() {
    const { path, cwd } = this.options
    return nodePath.isAbsolute(path) ? path : nodePath.join(cwd, path)
  }

  get extention() { 
    const { path } = this.options
    return nodePath.extname(path)
  }

  async contents() {
    return readFile(this.fullPath, { encoding: 'utf8' })
  }

  async main() { 
    return {
      ...this.options,
      fullPath: this.fullPath,
      extention: this.extention,
      contents: await this.contents(),
    }
  }
}

const file = new FileLoader({ cwd: './', path: 'README.md' })

file.main().then(console.log)

Этот вопрос заключается в том, чтобы найти способ написать методы класса, которые позволяют мне делать то, что я объяснил выше.

...