(显然这与typescript没什么关系,只是示例代码在ts中。)
import { createWriteStream, WriteStream } from "fs";
export class Util {
public static openWrite(path: string): Promise<WriteStream> {
return new Promise<WriteStream>((resolve, reject) => {
const result = createWriteStream(path);
const onError = (err: Error) => {
// How to remove both listeners here?
reject(err);
}
const onOpen = (fd: number) => {
// How to remove both listeners here?
resolve(result);
};
result.on("error", onError);
result.on("open", onOpen);
});
}
}
代码应该说明一切。我很难看到函数应该如何编写,以便正确处理成功和失败场景,同时确保在完成所有操作后删除所有添加的事件处理程序。
当然,总是有可能调用removeAllListeners,但这看起来像是对我的黑客攻击。
答案 0 :(得分:1)
在NodeJS中,所有-Xmx14g
都是Stream
(https://nodejs.org/api/stream.html#stream_stream)
EventEmitter
有一个名为EventEmitter
的方法。因此,请尝试执行以下操作:
removeListener
答案 1 :(得分:0)
Here's what I finally went with ...
public static async openWrite(path: string): Promise<WriteStream> {
const factory = new StreamFactory(() => createWriteStream(path));
try {
return await factory.get();
} finally {
factory.dispose();
}
}
... with StreamFactory defined as follows:
class StreamFactory<T extends EventEmitter> {
private stream: T;
private onOpen: (fd: number) => void;
private onError: (err: Error) => void;
private readonly promise: Promise<T>;
public constructor(create: () => T) {
this.promise = new Promise<T>((resolve, reject) => {
this.stream = create();
this.onOpen = fd => resolve(this.stream);
this.onError = err => reject(err);
this.stream.on("open", this.onOpen).on("error", this.onError);
});
}
public get(): Promise<T> { return this.promise; }
public dispose(): void {
this.stream.removeListener("open", this.onOpen).removeListener("error", this.onError);
}
}
I've tested the failure and success paths of the above and the event handlers are removed correctly in both cases. Of course, this is just a variation of Jakes answer, so +1 to him for pointing this out.
This has the advantage of not resorting to Promise.finally
, which doesn't seem to be available on my platform (Node 8.x).
It appears that it is definitely not a good idea to use removeAllListeners()
. At least on my platform, the library itself seems to add a listener for "open"
when an error occurs. removeAllListeners()
would remove that with possibly unintended consequences.