是否有一个节点模块的常见模式,需要asynchronous加载大文件才有用?

我不喜欢我见过的任何东西…

import lineReader from 'line-reader' let bigFile = './huge-file.csv' export default class DooDad { constructor() { this.dictionary = new Map() // Something like this seems like it'd be nice... // await this.load() } load() { return new Promise((resolve, reject) => { lineReader.eachLine(bigFile, (line, last) => { // this.dictionary = The contents of huge-file.csv }) }) } doStuff(foo) { // Uses this.dictionary to do something interesting // Problem: Unusable without first calling and waiting for this.load() } } 

用法

 import DooDad from '../doodad' let doodad = new DooDad() // We have to first call and wait for load() before doodad is useable doodad.load().then(x => { doodad.doStuff() }) 

好像你想要…

1)使加载同步

2)在DooDad上create一个静态的create函数,该函数返回一个parsing为DooDad的新实例的promise

3)使构造函数返回一个Promise(看起来很奇怪) asynchronous构造函数

4)完成加载后发出事件

5)让它如何

6)

doodad.load().then()对我来说是完全有意义的。 你不希望构造函数是asynchronous的,所以.load()是asynchronous的东西是有意义的。

我见过的另一种模式是导出一个工厂types的函数,返回一个promise,当这个promise被parsing时,parsing的值就是完全形成的对象。 这样做的好处是,只有在完成asynchronous操作之后才能访问对象,并且在准备就绪之前没有通过调用代码来尝试使用它的诱惑。

 import makeDooDad from '../doodad' makeDooDad().then(doodad => { // you only get access to the object here after it's been fully // initialized doodad.doStuff(); }); 

而且, makeDooDad()工厂函数在你的模块内部做了这样的事情:

 function makeDooDad() { let d = new DooDad(); // fully initialize the doodad object before resolving the promise // and before returning the object return d.load().then(() => { // let the object itself by the resolved value return d; }); } 

至于你的其他select:

使加载同步

只有在服务器启动的时候才可以。 在服务器启动时进行一些同步I / O通常没有实际成本,而且通常会使事情变得简单得多。 例如, require()本身执行同步I / O。

在DooDad上创build一个静态创build函数,该函数返回一个parsing为DooDad的新实例的promise

这基本上是我在上面用工厂function推荐的。 这往往是一个不错的select。

使构造函数返回一个Promise(看起来很奇怪)asynchronous构造函数

不,不是真的想这样做。 构造函数应该返回对象,而不是承诺。 使用工厂函数来返回一个承诺。

完成加载后发出事件

还有其他一些代码可以做到这一点,例如创build一个writeStream,当stream实际打开时,在stream上发出一个open事件。 但是,在承诺的日子里,这不是我最喜欢的方式,为其他types的对象没有使用很多事件。

离开它是如何

没问题,但是我更喜欢那个返回承诺的工厂函数。