介绍

我的应用程序中有不同的功能,比如:

  1. 重置密码(忘记密码)
  2. 更新用户密码
  3. 注册
  4. 成为溢价

对于每个功能,如果成功,我想向用户发送一封自定义HTML邮箱.

邮箱的产生

由于HTML的主要 struct 是相同的(只有内容(文本)发生了变化),我决定实现我的助手方法generateEmailTemplate():

const { HEAD, BODY } = require("../utils");

module.exports = (main) => `
  <!DOCTYPE html>
  <html lang="en">
    ${HEAD}
    ${BODY(main)}
  </html>
`;

为了将特定数据包含到生成的模板中,我对每个功能使用了不同的方法:

const signUpWelcomeEmailTemplate = (name) => 
  templateGenerator(`<p>Welcome, ${name}</p>`);

const premiumEmailTemplate = (name) =>
  templateGenerator(`<h1>${name}, you are now premium!</h1>`); 

// The html is more complex, I have reduced it for simiplicity

发送邮箱

为了向用户发送邮箱,我有以下方法,将邮箱记录添加到我的数据库中.然后,当添加记录时,连接到MailGun服务的自定义扩展通过SMTP发送邮件.

这是我的方法的实现:

async function sendEmail(
  to,
  subject,
  text = undefined,
  html = undefined
) {
  const mailsRef = db.collection("mails");

  const mail = {
    to,
    message: {
      subject,
      ...text && { text },
      ...html && { html },
    },
  };

  await mailsRef.add(mail);

  functions.logger.log("Queued email for delivery!");
};

问题

现在,为了使用这种方法,在每个功能中,我必须执行以下操作:

async function goPremium(user) {
   try {
     await purchasePremium(user.uid);

     const html = premiumEmailTemplate(user.name);

     sendEmail(user.email, "Premium purchase success!", undefined, html);
   } catch(err) {
     ...
   }
}

我在寻找一种模式来概括这个电话,我的意思是,某种邮箱管理器.

我考虑过两种不同的方法来重构代码:

#1(我不喜欢这种方式,因为这个方法可能会很长,我的意思是,想象100个特征…)

   function emailManager(user, type) {
     switch(type) {
       "welcome":
         sendEmail(user.email, "Welcome!", undefined, welcomeEmailTemplate(user.name));
         break;

       "premium":
         sendEmail(user.email, "Premium purchase success!", undefined, premiumEmailTemplate(user.name));
         break;

       default:
         break;
     }
   }
  1. 只需创建不同的方法,并将其从"中心"模块导出即可.
...

const sendPremiumEmail = (user) => {
  const title = "Premium purchase success!";
  const html = premiumEmailTemplate(user.name);
  
  return sendEmail(user.email, title, undefined, html);
};

...

module.exports = {
  sendWelcomeEmail,
  sendPremiumEmail,
  ...
}

但是也许还有另一种方式,一种模式可以解决这种情况.有什么 idea 吗?

推荐答案

功能性风格——定义curried function sendEmail,并为高级邮箱和欢迎邮箱制作两个部分应用程序.

const sendEmail = (subject, template) => to => {
  const mailsRef = db.collection("mails");
  const html = template(to);
  const mail = {
    to,
    message: {
      subject,
      ...text && { text },  // unused
      ...html && { html },
    },
  };
  await mailsRef.add(mail);
  functions.logger.log("Queued email for delivery!");
}

const sendPremiumEmail = sendEmail("Premium purchase success!", premiumEmailTemplate);
const sendWelcomeEmail = sendEmail("Welcome", welcomeEmailTemplate);

// usage
await sendPremiumEmail('foo@email.com');

Javascript相关问答推荐

使用json文件字符串来enum显示类型字符串无法按照计算的enum成员值的要求分配给类型号

对象和数字减法会抵消浏览器js中的数字

使用AJX发送表单后,$_Post看起来为空

. NET中Unix时间转换为日期时间的奇怪行为

Spring boot JSON解析错误:意外字符错误

cypress中e2e测试上的Click()事件在Switch Element Plus组件上使用时不起作用

这个值总是返回未定义的-Reaction

覆盖TypeScrip中的Lit-Element子类的属性类型

为什么123[';toString';].long返回1?

在使用位板时,如何在Java脚本中判断Connect 4板中中柱的对称性?

变量在导入到Vite中的另一个js文件时成为常量.

未捕获的运行时错误:调度程序为空

使用父标签中的Find函数查找元素

try 将Redux工具包与MUI ToggleButtonGroup组件一起使用时出错

P5.js中的分形树

Node.js API-queryAll()中的MarkLogic数据移动

有没有办法通过使用不同数组中的值进行排序

使用Library chart.js在一个带有两个y轴的图表中绘制两个数据集

在每次重新加载页面时更改指针光标

此上下文在JavaScript中