有一个新的上下文管理器。with
悄然死去,所以自然是时候重新品牌和复兴了:)
设置:看着新的using
关键字,我立即发现了一个场景,它将是一个非常棒的模式。Google Cloud Platform(GCP)的云功能有log()
、warn()
和error()
。很多时候,我需要先在本地运行它们,有些日志非常广泛。我不想通过终端窗口查看,我想从一个帮助文件导入我自己的这些函数的实现,保持实现语法不变。这将允许我在本地文件夹中拥有用于调试和测试的.log
文件。
我一直在努力做到这一点:
// localLogger.ts
import { createWriteStream } from "fs"
import { fileURLToPath } from "url"
import { dirname, join } from "path"
export function wrapLogs(
callee: string,
type: "info" | "warn" | "error" = "info"
) {
const logs: {
when: string
logs: string
payload?: any
}[] = []
const __importFile = fileURLToPath(import.meta.url)
const __logFileDir = dirname(__importFile)
const __logFile = join(__logFileDir, "../logs", `${type}.log`)
const stream = createWriteStream(__logFile, {
flags: "a",
encoding: "utf8",
})
return function (input?: string, payload: any = {}) {
if (input) {
const timeStamp = new Date().toISOString().split("T")[1].slice(0, -1)
logs.push({ when: timeStamp, logs: input })
if (Object.keys(payload).length) {
logs[logs.length - 1].payload = payload
}
}
return {
callee,
logs,
done: () => {
logs.forEach((log) => {
stream.write(`${log.when} - [${callee}] - ${type}: ${log.logs}\n`)
if (log.payload) {
stream.write(`payload: ${JSON.stringify(log.payload, null, 2)}\n`)
}
})
stream.on("finish", () => {
console.log("done")
})
stream.end()
},
}
}
}
这很接近,但不是雪茄。这个实现需要在每个实现日志记录器的函数的末尾运行.done()
方法--这并不理想,因为这为健忘的错误留下了很大的空间。这就是using
理论上应该发挥作用的地方。
// implementer.ts
import { wrapLogs } from './localLogger.ts'
function myCloudFuntion(){
const log = wrapLogs('myCloudFunction')
// does something and then logs
const data = { payload: 'relevant data' }
log("some useful log here", data)
// more stuff
log().done() // <- this part i would like to do without
return
}
所以在理想的世界里,我想这样定义日志记录器:
// localLogger.ts
...
// last return of the wrapLogs definition
return {
callee,
logs,
[Symbol.dispose]() {
logs.forEach((log) => {
stream.write(`${log.when} - [${callee}] - ${type}: ${log.logs}\n`)
if (log.payload) {
stream.write(`payload: ${JSON.stringify(log.payload, null, 2)}\n`)
}
})
stream.on("finish", () => {
console.log("done")
})
stream.end()
},
}
在实施文件中:
// implementer.ts
function myCloudFunction(){
using log = wrapLogs("myCloudFunction")
//...
log("some message", data)
return // <- no more log().done()
}
不幸的是,这引起了各种各样的问题。欢迎任何帮助。这些是我进入单子领域和using
的第一步,所以要温柔:)
1条答案
按热度按时间qv7cva1a1#
看起来你正在尝试使用TypeScript中的using关键字实现一个自定义上下文管理器,类似于Python中的with关键字。虽然TypeScript没有像Python那样内置上下文管理器,但您可以通过一些修改来实现类似的功能。
这里有一种方法,允许您创建自定义日志记录器并自动关闭它们,而无需在实现文件中调用log().done():
1.修改
localLogger.ts
文件:在
localLogger.ts
文件中,可以创建一个自定义日志记录器类,它充当上下文管理器。这个类可以管理日志的打开和关闭。2.在您的
implementer.ts
文件中实现日志:现在,在您的实现文件中,您可以使用
wrapLogs
函数来创建一个logger并自动关闭它,而无需显式调用log().done()
。使用这种方法,您可以创建一个Logger类,用于处理打开、记录和关闭日志。日志记录器在超出作用域时自动关闭,这样就不需要在实现文件中显式调用log().done()。