简体   繁体   English

使用 fp-ts 重写一个用记录器包装的小函数

[英]Rewriting a small function wrapped with a logger using fp-ts

I wanted to try to rewrite some parts of my code using fp-ts and considered to refactor the following method:我想尝试使用 fp-ts 重写我的代码的某些部分,并考虑重构以下方法:

export const createApiServer = () => {
    logger.info("Starting World Server API");

    const apiServer = express()
        // 3rd party middleware
        .use(helmet())
        .use(bodyParser.json())
        .use(cors())
        // Root route
        .get("/", (_, result) => result.sendStatus(httpStatusCodes.OK))
        // 404 - Not Found
        .use((_, result) => result.sendStatus(httpStatusCodes.NOT_FOUND))
        // 500 - Internal Server Error
        .use(errorLoggerMiddleware)
        .use(errorResponseMiddleware);

    logger.verbose(`Initialized World Server API in ${process.uptime().toFixed(3)} seconds`);

    return apiServer;
};

After reading about the IO type for sideffects I tried using it as follows:在阅读了关于副作用的IO类型后,我尝试使用它,如下所示:

const info = (message: string) => new IO(() => log.info(message));
const verbose = (message: string) => new IO(() => log.verbose(message));

const setupApiServer = () =>
    new IO(() =>
        express()
            .use(helmet())
            .use(bodyParser.json())
            .use(cors())
            .get("/", (_, result) => result.sendStatus(httpStatusCodes.OK))
            .use((_, result) => result.sendStatus(httpStatusCodes.NOT_FOUND))
            .use(errorLoggerMiddleware)
            .use(errorResponseMiddleware)
    );

export const createApiServer = () =>
    info("Starting World Server API")
        .chain(setupApiServer)
        .chain((apiServer) =>
            verbose(`Initialized World Server API in ${process.uptime().toFixed(3)} seconds`)
                .map(() => apiServer)
        )
        .run();

It feels rather weird to arbitrarily use the map method to pipe through the apiServer object in the last chain call just to log inbetween receiving it and send it further.在最后一个链调用中随意使用 map 方法通过 apiServer 对象进行管道传递,只是为了在接收它并进一步发送它之间进行登录,这感觉很奇怪。 I'd like to know whether this is correct or whether there are any different patterns for this.我想知道这是否正确,或者是否有任何不同的模式。

You can use chainFirst .您可以使用chainFirst

With chainFirst you can refactor this使用chainFirst你可以重构这个

import { pipe } from "fp-ts/lib/pipeable";
import * as IO from "fp-ts/lib/IO";

declare const log: (m: string) => IO.IO<void>
declare const a: IO.IO<number>

pipe(
  a,
  IO.chain((a) => pipe(log(`Got ${a}`), IO.map(() => a)))
)

into this进入这个

pipe(
  a,
  IO.chainFirst((a) => log(`Got ${a}`))
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM