收藏
评论

一种极简单的云函数归一化实现方式

第一次做小程序云开发,昨晚第一次需要切换后台环境,发现如果要切换环境的话,需要逐个云函数修改它的

cloud.init({

   env: "环境ID"

});


方法,在里面加入要切换的环境的环境id,并且切换之后需要逐个云函数部署到云后台去——这着实让人难受。


于是准备进行云函数归一的工作,即,将所有云函数写在同一个云函数内,实现 “如果需要切换环境,只需要修改一个文件,部署一个云函数即可” 的效果。经过一些摸索,卓有成效,下面将一些经验分享给大家。


首先,我希望达到的目标是:

  1. 实现归一化:让所有云函数功能都写在一个云函数中。

  2. 易接入:

    1. 不要对现有的云函数有太大的改动。一些云函数比较复杂,改动太大容易出bug。

    2. 小程序端的接入方式也不要有太大的改动,不然也容易出问题。

  3. 可维护:尽量避免由于实现归一化,而增加不同云函数间的耦合,尽可能和原有的云函数机制一样,不同的云函数各自隔离。

  4. 好扩展:以后再新增云函数,不要修改太多地方。最好像现有云函数一样,右键新建,然后就可以开始写功能了。


为了实现以上目标,我采用了如下方案:

       1. 云后台端:


        a. 新建一个router云函数,在其内新建一个function文件夹,将其他所有云函数的 index.js 的名称改为云函数的名字,并放入function文件夹。进行这一步之后,router云函数的目录结构为:


    └─router
        │  index.js(“router”云函数的index文件)
        │  newFuncTemplate.js
        │  package.json
        
        └─functions
                onClick.js(原“onClick”云函数的index文件)
                publish.js(原“publish”云函数的index文件)
        b. 修改 router 云函数的 index.js 函数,根据从event中取出来的 funcName 进行云函数寻址,并将任务分发下去。注意:为了实现所有云函数都能一键切换环境,需要将 cloud 传下去,让其他云函数都用 router 的 index.js 里面的 cloud。

        

    // 云函数入口文件
    const cloud = require('wx-server-sdk');
    cloud.init();
     
    // 云函数入口函数
    exports.main = async (event, context) => {
      log(event , "收到云函数调用");
      const funcMain = require("./functions/" + event.funcName + ".js");// 根据funcName寻址云函数
      return await funcMain(event, context , cloud);// 将任务分发下发。此处要将 cloud 传下去
    };


      c. 修改 function 文件里面的所有云函数文件,主要由两个修改点:

            c1. 需要使用构造函数里面传进来的cloud。

            c2. 需要将入口函数暴露出去。

            修改结束之后的各个云函数文件如下所示:


    2. 小程序端

        小程序端需将所有请求的 name 都改为 router,并且在传的 data 里面加上 funcName 参数,其值为之前原本要调的云函数方法名。

    // 修改前
    wx.cloud.callFunction({
        name: "deleteMyPublish",
        data: {
            id: key
        },
        success: res => {}
    })
    // 修改后
    wx.cloud.callFunction({
        name: 'router',
        data: {
            funcName: "deleteMyPublish",
            id: key
        },
        success: res => {}
    })


    3.  后续新增云函数

        后续新增的话,就直接在 function 文件夹里面新建一个以云函数命名的 js 文件,然后把上面 1.c 里面的代码复制进去,就可以直接写逻辑了。


    大概就是这样了。这个编辑器真的很难用,什么时候能支持 Markdown ?

最后一次编辑于  2018-12-25
赞 1
收藏

4 个评论

  • 逆水寒
    逆水寒
    03-27

    我也做了类似的结构,这个问题的根源还是在于云函数的环境无法自动切换,不管你部署到哪个环境,都要手动指定 env,如果能自动读取部署环境就没这个问题了,还有就是类似全局工具的,现在的云函数是函数间隔离的,这就导致一些工具类无法共用,种种原因吧

    03-27
    赞同
    回复
  • 老张
    老张
    01-03

    仁者见仁吧,这种模式so far未见有什么好处。

    01-03
    赞同
    回复 3
    • lypeer
      lypeer
      01-07

      主要好处有两点: 1,不用一个一个部署云函数

      2,切换环境可以一键切换

      01-07
      回复
    • 老张
      老张
      01-08回复lypeer

      你改一个标点符号都得重新部署一次,以前是改函数A部署一次A,改函数B部署一次B,现在是改A部署一次router,改B也部署一次router。如果A的npm依赖和B的依赖不相同,你还得每次都安装所有依赖。

      明明是更复杂,更不合理了。

      01-08
      回复
    • 陈三星
      陈三星
      04-16

      赞同楼上各位, 意义不是特别大。


      调用次数没有节省, 就是云函数个数节省了。


      可以自动读取当前部署的环境就好了!

      04-16
      1
      回复
  • Dyson_Open
    Dyson_Open
    2018-12-30

    有点意思,这样的话云函数调用次数就节省很多了


    /个性签名,不服不行


    2018-12-30
    赞同
    回复 1
    • 老张
      老张
      01-03

      呵呵,次数一点也没少吧。无非是:

      调用A=调用router(A):都是一次

      调用B=调用router(B):还是都算一次。

      01-03
      回复
  • lypeer
    lypeer
    2018-12-25
    // 云函数入口文件
    var cloud;
    var db;
    var _;


    // 云函数入口函数
    const main = async(event, context , clo) => {
    cloud = clo;
       db = cloud.database();
       _ = db.command;
    };


    module.exports = main;

    这段代码贴在正文里死活无法发布成功,迫于无奈,在这里贴一下。

    2018-12-25
    赞同
    回复