Skip to content

Some gentle criticism of this proposal #78

@nr-goby

Description

@nr-goby

I've been looking over the proposal and I'm not quite convinced that it is necessary. Let's look at your code example:

async function handle(request, reply) {
  const userInfo = try await cache.getUserInfo(request.id)

  if (!userInfo.ok) {
    logger.error(userInfo.error, "Maybe DB is down?")
    return reply.status(500).send({ error: "Could not get user info" })
  }

  const posts = try await db.getPosts(userInfo.value.authorId)

  if (!posts.ok) {
    logger.error(posts.error, "Anonymous user behavior not implemented yet")
    return reply.status(500).send({ error: "Could not get posts" })
  }

  const comments = try await db.getComments(posts.value.map((post) => post.id))

  if (!comments.ok) {
    logger.error(comments.error, "Posts without comments not implemented yet")
    return reply.status(500).send({ error: "Could not get comments" })
  }

  // No need for reassignable variables or nested try/catch blocks

  // Do something with comments before returning
  return reply.send({ userInfo: userInfo.value, posts: posts.value, comments: comments.value })
}

I believe you can easily achieve this in Javascript as of today in an alternate way, let me show you:

async function handle(request, reply) {
  // userInfo: User | void
  const userInfo = await cache
    .getUserInfo(request.id)
    // since our logger returns void, we can use that value as our reciprocal value to branch on
    .catch((err) => logger.error(err, "Maybe DB is down?"));

  // now we can check on existence and return our reply status, could also be userInfo !== undefined
  if (!userInfo)
    return reply.status(500).send({ error: "Could not get user info" });

// userInfo now narrowed to User
// userInfo: User 

// posts: Post[] | void
  const posts = await db
    .getPosts(userInfo.authorId)
    .catch((err) =>
      logger.error(err, "Anonymous user behavior not implemented yet")
    );

  if (!posts) return reply.status(500).send({ error: "Could not get posts" });

// comments: Comment[] | void
  const comments = await db
    .getComments(posts.map((post) => post.id))
    .catch((err) =>
      logger.error(err, "Posts without comments not implemented yet")
    );

  if (!comments)
    return reply.status(500).send({ error: "Could not get comments" });

  // No need for Result objects to complicate our logic

  return reply.send({
    userInfo,
    posts,
    comments,
  });
}

I know it's just a small example, but you gave an example that uses only promises and promises have pretty good error handling built into them. Can you maybe show another example that your proposal would provide a better solution for?

Metadata

Metadata

Assignees

No one assigned

    Labels

    FeedbackFeedback, usages and examples

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions