Observables в nestjs - асинхронное чтение файла - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь использовать случай асинхронного чтения файла 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 Ответ

0 голосов
/ 19 февраля 2019

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

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

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);
        }
    });
});
...