简体   繁体   English

努力使用Ramda.js重构这个,这是我有多远

[英]Struggling to refactor this using Ramda.js, here is how far I got

I'm learning Ramda.js. 我正在学习Ramda.js。 The function I'm trying to refactor using Ramda is below. 我试图使用Ramda重构的函数如下。 It calls a function firestore database method to get some data. 它调用函数firestore数据库方法来获取一些数据。 But firestore returns data inside a snapshot method and we need to call .data() . 但是firestore在snapshot方法中返回数据,我们需要调用.data() Depending on the result, I want to construct different response. 根据结果​​,我想构建不同的响应。

Would love to here your thought process 愿你喜欢这里的思考过程

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);
  }
}

...and here is what I have been able to refactor, would love to see better/other ways of doing this (I'm not sure if this even works). ......这就是我能够重构的,我希望看到更好/其他方式(我不确定这是否有效)。 I'm struggling with the sendResult method. 我正在努力使用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);
}

Here's the moving parts I see. 这是我看到的移动部件。 It's just one of the many possible ways to write the program – 这只是编写程序的众多可能方式之一 -

const tryCatch = f =>
  new Promise
    ( (resolve, reject) =>
        { try { resolve (f ()) }
          catch (err) { reject (err) }
        }
    )

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

const handleError = res => err =>
  res .status (500) .send (err)

const getSnapshot = (uid, docid) =>
  firestore
    .collection ("quizResults")
    .doc (uid)
    .collection ("courses_chapters")
    .doc (docid)
    .get ()
    .data ()

const queryForUsersQuizResults = (req, res) =>
  tryCatch
    ( () =>
        getSnapshot
          ( req.user.uid
          , req.params.courseId + "_" + req.params.chapterId
          )
    )
    .catch
      ( _ => Promise .reject (Error ("result not found for this user for this course and chapter"))
      )

const main = (req, res) =>
  queryForUsersQuizResults (req, res)
    .then
      ( handleSuccess (res)
      , handleError (res)
      )

And here's a working demo to show the concepts in action - 这是一个展示行动概念的工作演示 -

 const DB = { 1: "ant" , 2: "bear" , 3: "cuttlefish" } const queryForUsersQuizResults = (id = 0) => { if (DB[id] === undefined) throw Error (`no record for id: ${id}`) else return DB[id] } const tryCatch = f => { try { return Promise .resolve (f ()) } catch (err) { return Promise .reject (err) } } const fakeResponse = (status = 200) => ({ send: data => console .log ("=>", status, data) , status: n => fakeResponse (n) }) const demo = (req, res) => tryCatch (() => queryForUsersQuizResults (req.params.uid)) .then ( data => res .send (data) , err => res .status (500) .send (err) ) demo ( { params: { uid: 1 } } , fakeResponse () ) // => 200 ant demo ( { params: { uid: 2 } } , fakeResponse () ) // => 200 bear demo ( { params: { uid: 3 } } , fakeResponse () ) // => 200 cuttlefish demo ( { params: { uid: 4 } } , fakeResponse () ) // => 500 Error: no record for id: 4 

I also think that what you have already is fine, if you really wanted to use composition, it could be something like this: 我也认为你已经很好,如果你真的想使用合成,它可能是这样的:

export const sendResult = (snapshot, response) =>
  pipe(getDataFromSnapshot, flip(send)(response))
    (snapshot);

You need to use flip as you don't have (at the time of the pipe definition) the result of getDataFromSnapshot(snapshot) yet, but you already have the object holding the implementation of your send method. 您需要使用flip因为在管道定义时getDataFromSnapshot(snapshot)没有getDataFromSnapshot(snapshot)的结果,但是您已经拥有了持有send方法实现的对象。

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

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