我不喜欢到目前为止所看到的任何事情......
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
函数,该函数返回一个解析为DooDad新实例的promise
3)使构造函数返回Promise(看起来很奇怪)Asynchronous constructor
4)完成加载后发出一个事件
5)保持原样
6)????
答案 0 :(得分:2)
doodad.load().then()
对我来说非常有意义。您不希望构造函数是异步的,因此让.load()
成为异步内容的位置是有意义的。
我见过的另一种模式是导出一个返回promise的工厂类型函数,当解析该promise时,解析后的值就是完全形成的对象。这样做的好处是,在完成异步操作之前无法访问该对象,并且在准备好之前调用代码尝试使用它是没有诱惑的。
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;
});
}
至于你的其他选择:
使加载同步
仅当它仅在服务器启动时完成时才可以。在服务器启动时执行某些同步I / O通常没有实际成本,并且通常会使事情变得更加简单。例如,require()
本身执行同步I / O.
在DooDad上创建一个静态创建函数,该函数返回一个解析为DooDad的新实例的promise
这基本上就是我上面推荐的工厂功能。这通常是一个不错的选择。
让构造函数返回一个Promise(看起来很奇怪)异步构造函数
没有。真的不想那样做。构造函数应返回对象,而不是承诺。使用工厂函数返回承诺。
完成加载时发出事件
还有其他一些代码可以执行此操作,例如创建writeStream,当流实际打开时,会在流上发出open
事件。但是,在承诺的时代,对于尚未使用大量事件的其他类型的对象,这不是我最喜欢的做事方式。
保持原样
它没关系,但我更喜欢返回承诺的工厂函数。