@Mazino

Как определить асинхронный параметр в конструкторе класса (ES2015 syntax)?

В приведенном коде хочу использовать 'fs/promises' api
Идея в том, чтобы сделать свойством экземпляра аксесор к файлу, но он доступен только в promises api, а конструктор не может быть асинхронным.
'use strict'

const _ = require('lodash')
const path = require('path')
const { promises: fs, watch } = require('fs')
const EventEmmiter = require('events')
const watcher = Symbol('watcher')

/**
 * @param {String} filename Path to file
 * @param {Object} options Settings object
 * @returns {EventEmmiter} Fires when file will changed
 */
class Tail extends EventEmmiter {
  constructor(filename, options = {}) {
    super()
    this.target = filename
    this.fileLastState = null
    this.file = fs.open(filename, 'r') /** Вот здесь свойство устанавливается как Promise,
    что ожидаемо, но даже после разрешения мы имеем:
    Promise {
      FileHandle {
        close: [Function: close],
          [Symbol(kHandle)]: FileHandle { fd: 3 }
      }
    }*/

    this.options = { ...options }
    this[watcher] = watch(this.target, "utf8", _.throttle(this.onChange.bind(this), 50, {
      "trailing": false
    }))
  }

  async onChange(event, filename) {
    if (event === 'change') {
      try {
        //Здесь бы хотелось что-то вроде await this.file.stat()
        //await (await this.file).stat() - не хотелось бы
      } catch (e) {
        console.error(e)
      }
    }
  }
}
const tail = new Tail(path.join(__dirname, 'data.json'))

По сути при первом вызове onChange промис уже точно будет разрешен, но доступ к свойству получается такой себе. Лучший вариант, что я смог родить:
constructor(filename, options = {}) {
    super()
    this.target = filename
    this.fileLastState = null
    this.file = null
    fs.open(filename, 'r').then(fileHandle => { this.file = fileHandle })
}

Но тогда при втором и последующем вызовах stat()
на this.file возвращаются неверные атрибуты, а именно размер файла становится равным 0, и только временные метки меняются
upd:
Такой вариант, лишен недостатка, о котором говорилось ранее
constructor(filename, options = {}) {
    super()
    this.target = filename
    this.fileLastState = null
    this.file = fs.open(filename, 'r').then(fileHandle => { this.file = fileHandle })
}

Теперь интересно, почему.
upd2:
Код конструктора тот же, код слушателя:
async onChange(event, filename) {
    if (event === 'change') {
      try {
        console.log(this) // Если это здесь, вызов ниже работает корректно. Если удалить, проблемы снова проявляются.
        console.log(await this.file.stat())
      } catch (e) {
        console.error(e)
      }
    }
  }

В js завезли квантовых эффектов?
  • Вопрос задан
  • 71 просмотр
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы