gpt4 book ai didi

javascript - 生成函数或异步生成函数后清理

转载 作者:搜寻专家 更新时间:2023-10-31 23:40:27 24 4
gpt4 key购买 nike

如何在生成函数退出后进行清理。我遇到的问题是我做了一个小实用程序来使用 Async Iterators 从文件中读取行一个第 3 阶段的 EcmaScript 提案,我希望它在我退出 for-of 循​​环后关闭它正在读取的文件。目前因为这个特性只是第 3 阶段,为了让它运行你必须使用 babel转译它。

通过下面的代码,您可以看到问题所在。如果您输入一个输入文件,那么它将读取一行并打印行阅读器仍然打开。

当迭代器返回时,我想在 LineReader 类中显式关闭文件。

我知道我可以通过不使用生成函数来做到这一点,而是返回一个迭代器对象,如概述 here ,但有什么方法可以保留生成函数并为其定义返回方法。

src/line-reader.js

function deferred() {
const def = {}
def.promise = new Promise((resolve, reject) => {
def.resolve = resolve
def.reject = reject
})
return def
}

/**
* PromiseQueue from GTOR adapted for ES2015
* https://github.com/kriskowal/gtor
*/
class PromiseQueue {
constructor (values) {
this.ends = deferred();
if (values) {
values.forEach(this.put, this);
}
}

put(value) {
const next = deferred();
this.ends.resolve({
head: value,
tail: next.promise
});
this.ends.resolve = next.resolve;
}

get () {
var result = this.ends.promise.then(node=>node.head);
this.ends.promise = this.ends.promise.then(node=>node.tail)
return result;
};
}

class LineReader {
constructor (input, output) {
this.lineReader = require('readline').createInterface({ input, output });
this.lineQueue = new PromiseQueue();
this.isClosed = false;
this.lineReader.on('line', (line) => {
this.lineQueue.put(line);
this.lineReader.pause();
});
this.lineReader.on('close', (line) => {
this.isClosed = true;
this.lineQueue.put(Promise.resolve({done: true}));
});
this.lineReader.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
this.lineReader.prompt();
});
}

readLine(){
var result = this.lineQueue.get().then(function (data) {
if(data && data.done) {
throw new Error("EOF");
}
return data
});
this.lineReader.resume();
return result;
}

close () {
this.lineReader.close();
}

async * [Symbol.asyncIterator] () {
try {
while(!this.isClosed) {
yield await this.readLine();
}
} catch (e) {
this.close();
}
}
}

module.exports = LineReader;

测试/测试.js

var LineReader = require("../src/line-reader");

var lineReader = new LineReader(process.stdin);

(async ()=> {
var i = 1;
for await (var line of lineReader) {
console.log(`${i++} ${line}`);
break;
}
console.log(`The line-reader is ${lineReader.isClosed ? "closed" : "open" }.`);
lineReader.close();
})().catch(e=> {
console.error(e)
})

最佳答案

您始终可以Object.assign 调用生成函数并使用return 扩展其返回的迭代器方法。

像这样:

class LineReader {
// ... elided code ...

async * iterate() {
try {
while(!this.isClosed) {
yield await this.readLine();
}
} catch (e) {
this.close();
}
}

[Symbol.asyncIterator] () {
return Object.assign(this.iterate(), {
return: () => {
this.close();
}
});
}
}

或者您也可以选择这种方式,但我更喜欢第一种,因为它不会在每次调用时都创建一个新函数,而且第一种对我来说看起来更好。

class LineReader {
// ... elided code ...

[Symbol.asyncIterator] () {
var that = this;
return Object.assign(async function * iterate() {
try {
while(!that.isClosed) {
yield await that.readLine();
}
} catch (e) {
that.close();
}
}(), {
return: () => {
this.close();
}
});
}
}

关于javascript - 生成函数或异步生成函数后清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46211404/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com