nestjs 中的 Observables - 异步读取文件
Observables in nestjs - Reading a file asynchronously
我正在尝试异步读取 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);
});
}
}
所以我想在控制器中订阅这个发出的 observable,但是在我订阅并阅读主题后,这些值正在被读取 (BehaviorSubject
)。我知道我在订阅和发送数据方面做错了,但不明白我做错了什么。每次控制器打印 'data subscribed undefined' 然后继续读取文件并发出 observable
这是控制器数据
@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;
}
所以我在异步读取文件时遗漏了一些东西。我不确定我做错了什么。有人可以帮忙吗?
问题是您实际上 return 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);
}
});
});
我正在尝试异步读取 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);
});
}
}
所以我想在控制器中订阅这个发出的 observable,但是在我订阅并阅读主题后,这些值正在被读取 (BehaviorSubject
)。我知道我在订阅和发送数据方面做错了,但不明白我做错了什么。每次控制器打印 'data subscribed undefined' 然后继续读取文件并发出 observable
这是控制器数据
@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;
}
所以我在异步读取文件时遗漏了一些东西。我不确定我做错了什么。有人可以帮忙吗?
问题是您实际上 return 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);
}
});
});