使用“函数工厂”生成相似函数

79 阅读2分钟

背景

当编写下面几个API的代码时,发现内容高度重合,于是想用某种方法减少代码量,并方便对其统一修改。

export const updatePassword = async (oPassword:string, nPassword:string) => {
  return new Promise((resolve, reject) => {
    axios.post('/api/user/updatePassword', {
      oPassword:oPassword,
      nPassword:nPassword
    }).then(response => {
      if(response.data==="修改成功"){
        alert('密码修改成功!');
        resolve(true);
      } else {
        alert('密码修改失败!');
        resolve(false);
      }
    }).catch(error =>{
      alert("updatePassword error!");
      reject(error);
    })
  });
}

export const updateNickname = async (nickname:string) => {
  return new Promise((resolve, reject) => {
    axios.post('/api/user/updateNickname', {
      nickname:nickname
    }).then(response => {
      if(response.data==="修改成功"){
        alert('昵称修改成功!');
        resolve(true);
      } else {
        alert('昵称修改失败!');
        resolve(false);
      }
    }).catch(error =>{
      alert("updateNickname error!");
      reject(error);
    })
  });
}

export const updatePhone = async (nPhone:string, code:string) => {
  return new Promise((resolve, reject) => {
    axios.post('/api/user/updatePhone', {
        nPhone:nPhone,
        code:code
    }).then(response => {
      if(response.data==="修改成功"){
        alert('手机号修改成功!');
        resolve(true);
      } else {
        alert('手机号修改失败!');
        resolve(false);
      }
    }).catch(error =>{
      alert("updatePhone error!");
      reject(error);
    })
  });
}

函数工厂

函数工厂是一种设计模式,它涉及使用一个函数(即工厂)来创建并返回另一个函数。这种模式非常适用于需要创建多个结构或行为类似的函数的场景。

使用场景:

假设我们正在开发一个需要不同类型的用户数据更新(如密码、昵称、手机号)的应用。每个更新操作都需要发送一个 API 请求,处理响应并进行错误处理。这些操作在逻辑上非常相似,因此是函数工厂模式的理想应用场景。

实现函数工厂:

我们创建一个 updateFunctionFactory 函数,它接受函数名、参数名称数组和中文关键词作为输入,并返回一个新的异步函数。这个异步函数负责发送 API 请求并处理响应。

import axios from 'axios';

function updateFunctionFactory(funcName: string, paramNames: string[], subjectChinese: string) {
  // 返回一个异步函数
  return async function (...args: any[]) {
    // 构造参数对象
    const params = args.reduce((obj, arg, index) => {
      obj[paramNames[index]] = arg;
      return obj;
    }, {});

    // 发送 API 请求并处理响应
    return new Promise<boolean>((resolve, reject) => {
      axios.post(`/api/user/${funcName}`, params).then(
        response => {
          if (response.data === "修改成功") {
            alert(`${subjectChinese}修改成功!`);
            resolve(true);
          } else {
            alert(`${subjectChinese}修改失败!`);
            resolve(false);
          }
        }).catch(error => {
          alert(`${funcName} error!`);
          reject(error);
        });
    });
  };
}

使用工厂函数:

我们可以使用 updateFunctionFactory 来创建针对不同更新操作的函数:

export const updatePassword: (oPassword: string, nPassword: string) => Promise<boolean> 
  = updateFunctionFactory('updatePassword', ['oPassword', 'nPassword'], '密码');
  
export const updateNickname: (nickname: string) => Promise<boolean>
  = updateFunctionFactory('updateNickname', ['nickname'], '昵称');
  
export const updatePhone: (nPhone: string, code: string) => Promise<boolean> 
  = updateFunctionFactory('updatePhone', ['nPhone', 'code'], '手机号');

结论

使用函数工厂模式可以显著减少重复代码,并提高代码的可维护性和可扩展性。这种模式特别适合于需要创建多个结构或行为相似的函数的场景,如 API 调用。