javascript - 努力使用 Ramda.js 重构它,这是我所取得的进展

标签 javascript functional-programming ramda.js

我正在学习 Ramda.js。我尝试使用 Ramda 重构的函数如下。它调用函数 firestore 数据库方法来获取一些数据。但是 firestore 在 snapshot 方法中返回数据,我们需要调用 .data()。根据结果​​,我想构造不同的响应。

很乐意在这里分享您的思考过程

const queryForUsersQuizResults = async (request, response) => {
  try {
    const snapshot = await firestore
      .collection("quizResults")
      .doc(request.user.uid)
      .collection("courses_chapters")
      .doc(request.params.courseId + "_" + request.params.chapterId)
      .get();

    let data = snapshot.data();
    if (!data) {
      data = {
        message: "result not found for this user for this course and chapter"
      };
    }

    return response.send(data);
  } catch (error) {
    return response.status(500).send(error);
  }
}

...这是我能够重构的内容,希望看到更好/其他的方法来做到这一点(我不确定这是否有效)。我正在努力使用 sendResult 方法。

//get user id
export const getUserId = pathOr('', ['user', 'uid']);

// get chapter id
export const getChapterId = concat(pathOr('', ['params', 'courseId']), '_', pathOr('', ['params', 'chapterId']));

//queryQuizResult
export const query = curry(async (firestore, request) => {
  return tryCatch(() =>
    firestore
    .collection("quizResults")
    .doc(getUserId(request))
    .collection("courses_chapters")
    .doc(getChapterId(request))
    .get(), F)();
});

//Receives "response" object and calls response.status with the value passed to the new status function
export const status = invoker(1, "status");

//Receives "response" object and calls response.send witht he value passed to the new send function
export const send = invoker(1, "send");

//Create {"message",Your_Error} object
export const constructError = objOf('message');

//Returns JSON from Firestore's snapshot object
export const getDataFromSnapshot = (snapshot) => snapshot.data();

//Actual error message
const QUIZ_RESULTS_NOT_FOUND = "Quiz results not found for this user for this course and chapter";

//Returns error message
export const quizResultsNotFoundError = constructError(QUIZ_RESULTS_NOT_FOUND);

//Receives "response" object and calls response.status and then respose.send
export const sendError = pipe(
  status(401),
  send(quizResultsNotFoundError)
);
//Sends valid result  //IS there any better way of doing this?
export const sendResult = (snapshot, response) => {
  const data = getDataFromSnapshot(snapshot);
  response.send(data); //Especially this, I wanted to use the "send" method and pipe things
}

//Main Method
export const  queryForUsersQuizResults = async (firestore, request, response) => {
 const snapshot = await query(firestore, request);
 snapshot ? sendResult(snapshot, response) :sendError(response);
}

最佳答案

这是我看到的事件部件。这只是编写程序的多种可能方法之一。我们将从一个通用助手开始 get来自 Firestore 请求的数据 -

const getData = doc =>
  doc.exists
    ? doc .data ()
    : Promise .reject (Error ("not found"))

我们现在可以编写一个queryForUsersQuizResults,但我们要小心地使其与路由处理程序请求响应分开 -

const queryForUsersQuizResults = (uid, docid) =>
  firestore
    .collection ("quizResults")
    .doc (uid)
    .collection ("courses_chapters")
    .doc (docid)
    .get ()
    .then (getData) // <- getData

现在我们编写 myRouterequest 参数传递给 queryForUsersQuizResults 并返回 `response -

const myRoute = (req, res) =>
  queryForUsersQuizResults
    ( req.user.uid
    , req.params.courseId + "_" + req.params.chapterId
    )
    .then
      ( handleSuccess (res)
      , handleError (404) (res)
      )

这取决于可以链接到任何 Promise 的通用处理程序 handleSuccesshandleError -

const handleSuccess = res => data =>
  res .send (data)

const handleError = code => res => err =>
  res .status (code) .send (err.message)

演示

这是一个工作演示,展示了实际的概念。 由于我们在 stacksnippets 中没有可用的数据库、firestoreexpress,因此我们必须模拟它们 -

const DB =
  { 1: "ant"
  , 2: "bear"
  , 3: "cuttlefish"
  }

const fakeFirestore = id =>
  new Promise
    ( r =>
        DB[id] === undefined
          ? r ({ exists: false })
          : r ({ exists: true, data: () => DB[id] })
    )

const fakeResponse = (status = 200) =>
  ({ send: data =>
       console .log ("=>", status, data)
   , status: n =>
       fakeResponse (n)
  })

我们将测试对每个数据库记录和不存在记录的查询 -

myRoute
  ( { params: { uid: 1 } }
  , fakeResponse ()
  )

myRoute
  ( { params: { uid: 2 } }
  , fakeResponse ()
  )

myRoute
  ( { params: { uid: 3 } }
  , fakeResponse ()
  )

myRoute
  ( { params: { uid: 4 } }
  , fakeResponse ()
  )

展开下面的代码片段以在您自己的浏览器中验证结果 -

const getData = doc =>
  doc.exists
    ? doc .data ()
    : Promise .reject (Error ("not found"))

const handleSuccess = res => data =>
  res .send (data)

const handleError = code => res => err =>
  res .status (code) .send (err.message)

const fakeResponse = (status = 200) =>
  ({ send: data =>
       console .log ("=>", status, data)
   , status: n =>
       fakeResponse (n)
  })
  
const fakeFirestore = id =>
  new Promise
    ( r =>
        DB[id] === undefined
          ? r ({ exists: false })
          : r ({ exists: true, data: () => DB[id] })
    )

const queryForUsersQuizResults = (id = 0) =>
  fakeFirestore (id)
    .then(getData)

const myRoute = (req, res) =>
  queryForUsersQuizResults (req.params.uid)
    .then
      ( handleSuccess (res)
      , handleError (404) (res)
      )

const DB =
  { 1: "ant"
  , 2: "bear"
  , 3: "cuttlefish"
  }

myRoute
  ( { params: { uid: 1 } }
  , fakeResponse ()
  ) // => 200 ant

myRoute
  ( { params: { uid: 2 } }
  , fakeResponse ()
  ) // => 200 bear

myRoute
  ( { params: { uid: 3 } }
  , fakeResponse ()
  ) // => 200 cuttlefish

myRoute
  ( { params: { uid: 4 } }
  , fakeResponse ()
  ) // => 404 not found

=> 200 ant
=> 200 bear
=> 200 cuttlefish
=> 404 not found

关于javascript - 努力使用 Ramda.js 重构它,这是我所取得的进展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53896356/

相关文章:

javascript - 删除字符串中单词开头和结尾的标点符号

javascript - 如何编写验证函数

javascript - 当我尝试插入两条记录时,CUR_STOCK 表中只有一条记录得到更新?

javascript - 如何使 Windows 应用商店应用程序非全屏?

OSGi 上下文中的 Scala-cat 的 IOApp

list - 从 lisp 中的列表中评估函数

function - Ocaml 中参数的求值顺序

javascript - lambda : rewriting to point free style

javascript - 为什么我的 Ramda 管道功能不能与过滤器一起使用?

javascript - 元组类型的问题