466 words
2 minutes
[Effect Config] 03. 定义环境变量

定义环境变量#

https://github.com/typeonce-dev/effect-getting-started-course

TIP

环境变量配置

默认情况下,Effect 从默认环境中提取 Config 值。对于 Node.js,这就是 process.env

然后我们需要做的就是在运行应用程序时定义这个配置。让我们更新 package.json 中的 dev 命令:

{
  "name": "effect-getting-started-course",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "dev": "BASE_URL=https://pokeapi.co tsx src/index.ts"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^20.14.10",
    "tsx": "^4.16.2",
    "typescript": "^5.5.3"
  },
  "dependencies": {
    "effect": "^3.10.0"
  }
}

现在我们可以执行 pnpm run dev,应用程序按预期工作:

> effect-getting-started-course@1.0.0 dev
> BASE_URL=https://pokeapi.co tsx src/index.ts

{ id: 445, order: 570, name: 'garchomp', height: 19, weight: 950 }

IMPORTANT

实现里程碑

我们的实现确实达到了一个稳固的状态。作为单个程序,这工作得很好。

import { Schema } from "effect";
import { Config, Data, Effect } from "effect";

/** Schema 定义 **/
class Pokemon extends Schema.Class<Pokemon>("Pokemon")({
  id: Schema.Number,
  order: Schema.Number,
  name: Schema.String,
  height: Schema.Number,
  weight: Schema.Number,
}) {}


/** 错误类型 **/
class FetchError extends Data.TaggedError("FetchError")<{}> {}
class JsonError extends Data.TaggedError("JsonError")<{}> {}


/** 配置 **/
const config = Config.string("BASE_URL");


/** 实现 **/
const fetchRequest = (baseUrl: string) =>
  Effect.tryPromise({
    try: () => fetch(`${baseUrl}/api/v2/pokemon/garchomp/`),
    catch: () => new FetchError(),
  });

const jsonResponse = (response: Response) =>
  Effect.tryPromise({
    try: () => response.json(),
    catch: () => new JsonError(),
  });

const decodePokemon = Schema.decodeUnknown(Pokemon);

const program = Effect.gen(function* () {
  const baseUrl = yield* config;
  const response = yield* fetchRequest(baseUrl);
  if (!response.ok) {
    return yield* new FetchError();
  }

  const json = yield* jsonResponse(response);

  return yield* decodePokemon(json);
});


/** 错误处理 **/
const main = program.pipe(
  Effect.catchTags({
    FetchError: () => Effect.succeed("Fetch error"),
    JsonError: () => Effect.succeed("Json error"),
    ParseError: () => Effect.succeed("Parse error"),
  })
);


/** 运行 Effect **/
Effect.runPromise(main).then(console.log);

Effect Playground

WARNING

向生产应用架构转变

然而,我们通常不会用单个函数构建应用程序,对吧?我们需要一种更强大的方式来组织代码和模块。测试怎么办?我们如何注入模拟实现?

准备好,我们即将从”如何实现一个 Effect 函数”转向**“如何使用 Effect 来组织生产应用程序”**。

这就是 Effect 赋予你的真正力量,让我们看看如何做到!