В приведенном коде хочу использовать '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 завезли квантовых эффектов?