Observables в nestjs - асинхронное чтение файла

Я пытаюсь использовать случай асинхронного чтения файла JSON и отправки его в качестве ответа (в виде наблюдаемых данных rxjs). Вот сервис, которым я пользуюсь

 import { logger } from './../../shared/utils/logger';
import { Injectable } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import { BehaviorSubject, Observable, pipe, of, from, throwError, merge} from 'rxjs';
import { map, filter, scan, take, debounce, switchMap, retry, catchError, mergeMap, delay, zip, tap, mapTo } from 'rxjs/operators';
import { HttpResponseModel } from '../model/config.model';
import { isNullOrUndefined } from 'util';
@Injectable()
export class NewProviderService {
    serviceSubject: BehaviorSubject<HttpResponseModel[]>;
    filePath: string;
    httpResponseObjectArray: HttpResponseModel[];
    constructor() {
        this.serviceSubject = new BehaviorSubject<HttpResponseModel[]>([]);
        this.filePath = path.resolve(__dirname, './../../shared/assets/httpTest.json');
        this.setSubject();
    }


 readFileFromJSON() {
      this.readFileFromJsonSync();
      fs.exists(this.filePath.toString(), exists => {
        if (exists) {
           fs.readFile(this.filePath.toString(), 'utf-8', (err, data) => {
                logger.info('file read without parsin', data);
                this.httpResponseObjectArray = JSON.parse(data).HttpTestResponse;
                logger.info('array obj is:', this.httpResponseObjectArray);
                logger.info('file read after parsing', JSON.parse(data));
                return this.httpResponseObjectArray;
            });
        } else {
            return null;
        }

    });
}


getObservable(): Observable<HttpResponseModel[]> {
       // create an observable
        // return Observable.create(observer => {
        //     observer.next(this.readFileFromJSON());
        // });

        return of(this.readFileFromJsonSync()).pipe(map(data => {
            logger.info('inside obs methid', data);
            return data;
        }));

    }

    setSubject() {
        this.getObservable().subscribe(data => {
            logger.info('data before setting in sub', data);
            this.serviceSubject.next(data);
        });
    }
}

Поэтому я хотел подписаться на это излучаемое наблюдаемое в контроллере, но значения читаются после того, как я подписался и прочитал тему (BehaviorSubject). Я понимаю, что я делаю что-то не так с подпиской и передачей данных, но не могу понять, где я делаю неправильно. Каждый раз, когда контроллер печатает "данные подписаны неопределенными", а затем продолжает читать файл и выдавать наблюдаемое

Это данные контроллера

@Get('/getJsonData')
  public async getJsonData(@Req() requestAnimationFrame, @Res() res) {
    this.newService.serviceSubject.subscribe(data => {
      logger.info('data subscribed', data);
      res.status(HttpStatus.OK).send(data);
    });

  }

Это работает хорошо, если я читаю файл синхронно

замещать readFileFromJSON() с помощью следующего метода, и он работает хорошо

readFileFromJsonSync(): HttpResponseModel[] {
        const objRead = JSON.parse(fs.readFileSync(this.filePath.toString(), {encoding: 'utf-8'}));
        logger.info('object read is', objRead.HttpTestResponse);
        return objRead.HttpTestResponse;

    }

Поэтому я что-то упускаю при чтении файла асинхронно. Я не уверен, что я делаю не так. Может ли кто-нибудь помочь, пожалуйста?

1 ответ

Решение

Проблема в том, что вы ничего не возвращаете в readFileFromJSON, Это будет работать асинхронно fs.exists а также fs.readFile и соответствующие обратные вызовы, но результат от обратных вызовов игнорируется.

Вы должны использовать Promises вместо. Вы можете создать Promise сами или использовать библиотеку, как Bluebird, которая преобразует fs от основанного на обратном вызове API к Promise на основе API. Для получения дополнительной информации см эту ветку.

return new Promise(function(resolve, reject) {
    fs.readFile(this.filePath.toString(), 'utf-8', (err, data) => {
        if (err) {
            reject(err); 
        } else {
            const httpResponseObjectArray = JSON.parse(data).HttpTestResponse;
            resolve(httpResponseObjectArray);
        }
    });
});
Другие вопросы по тегам