前言
前几天对微信小程序云函数封装了路由分发,对微信小程序封装了 ServiceUtil
,今天我们来封装一下 job ,并升级一下 ServiceUtil
,源码在文章底部
上一篇: 封装微信小程序云函数(一)
云函数封装
首先看一下新的目录结构
其中 controller
和 model
跟上次介绍的没有变,所以这里就不介绍了,这里主要介绍一下 LeJob
的封装
封装 LeJob
首先我们来看 index
文件, index
文件主要定义了 LeRouter
和 LeJob
类
cloudfunctions\job\common\index.js
const LeBase = require('./LeBase')
const { checkRequestParams, getJobs } = require('./util/index')
class LeRouter extends LeBase {
constructor(options) {
super(options);
this.routers = options.routers || {};
}
run() {
return async (event, context) => {
const router = this.routers[event.$url];
// 若 router 没有找到则抛出 router not found
if (!router) {
throw Error('router not found')
}
// 引入 controller
const Controller = require(this.routers[event.$url]);
// 检查字段
checkRequestParams(event, Controller.rules);
// 执行 controller 中的 main()
return await Controller.main.call(this, event, context);
}
}
}
class LeJob extends LeBase {
constructor(options) {
super(options);
this.jobs = options.jobs || {};
}
run() {
return async (event, context) => {
// 获取应该执行的 job
const jobNames = getJobs(this, this.config.triggers);
if (jobNames) {
jobNames.forEach((jobName) => {
// 依次导入 job 并执行
const Controller = require(jobName);
Controller.main.call(this, event, context);
})
}
}
}
}
module.exports = { LeRouter, LeJob }
复制代码
LeRouter
和 LeJob
是继承自 LeBase
,我们看一下 LeBase
在 LeBase
主要是给实例化的对象封装 _cloud
、 config
、 DB
属性
// 初始化对象属性
function initAttr(options) {
this._cloud = require('wx-server-sdk');
this.config = options.config || {};
setDB.call(this);
}
// 初始化 DB
function setDB() {
Object.defineProperty(this, 'DB', {
configurable: false,
get() {
this._DB || (this._DB = require('./DB')(this));
return this._DB;
}
})
}
// 初始化 cloud
function initCloud() {
this._cloud.init({
env: this.config.env,
});
}
class LeBase {
constructor(options) {
initAttr.call(this, options);
initCloud.call(this);
}
}
module.exports = LeBase
复制代码
DB
文件与上次没有任何区别,在这里贴出看一下吧
cloudfunctions\router\common\DB.js
// 根据配置的 env 和 throwOnNotFound 初始化 database对象
function initDB(leOptions) {
const config = leOptions.config
return leOptions._cloud.database({
env: config && config.env,
throwOnNotFound: config && config.DBThrowOnNotFound,
});
}
module.exports = initDB
复制代码
我们看一下我们前面 index
文件用到的方法
cloudfunctions\router\common\util\index.js
...
...
function getJobs(LeJob, triggers) {
// 因为配置 job 使用 cron 语句,所以引入 cron-parser 来解析
const cronParse = require('cron-parser')
const { jobs } = LeJob;
const time = new Date().getTime() - 1;
return Object.keys(jobs).reduce((jobNames, key) => {
const intervalTime = cronParse.parseExpression(key).prev().getTime();
const job = jobs[key];
if (time - intervalTime <= triggers) {
// job 可以配置为字符串或对象
if (typeof job === 'string') {
jobNames.push(jobs[key]);
} else if (typeof job === 'object') {
jobNames.push(...jobs[key]);
}
}
return jobNames;
}, []);
}
module.exports= { checkRequestParams, getJobs }
复制代码
使用
那我们看一下我们云函数的 index
文件吧
cloudfunctions\job\index.js
const { LeJob } = require('./common/index')
const options = {
// 这里可以配置一些使用到的配置项
config: {
// 本云函数名
name: 'router',
// 这里单位为毫秒,需要与 config.json 文件中的 triggers 配置相同
triggers: 60 * 60 * 5 * 1000,
},
// 这里以 cron 格式的字符串为键,以 controller 的路径为值,值可以是数组或字符串
jobs: {
"0 0 17 * * 6": ["controller/hello/HelloWorld"],
},
}
const app = new LeJob(options)
exports.main = app.run()
复制代码
然后我们看一下 config.json
文件
这里就是配置一下 triggers
配置项, triggers
现在必须配置为间隔一定时间执行,如 5 个小时
cloudfunctions\job\config.json
{
"triggers": [
{
"name": "job",
"type": "timer",
"config": "* * */5 * * * *"
}
]
}
复制代码
controller
文件和 model
文件这里就不介绍了,跟之前的写法一样
小程序封装 ServiceUtil
先看一下目录
这个封装改动很小,就改动了一处
使用 ServiceUtil
时需要先实例化 ServiceUtil
,可以传入云函数名,以支持云函数分模块开发
miniprogram\engine\util\ServiceUtil.js
export default class ServiceUtil {
constructor(cloudName = CLOUD_NAME) {
this.cloudName = cloudName;
}
request = (url, data = {}, complete = (res) => {}) => {
...
...
}
callFunction = (url, data = {}, success = () => {}, fail = () => {}, complete = (res) => {}) => {
...
...
}
}
复制代码
所以我们使用的时候需要先实例化 ServiceUtil
,
miniprogram\engine\User.js
import ServiceUtil from './util/ServiceUtil.js'
const serviceUtil = new ServiceUtil('router')
export default class User {
static getById = async (id) => {
return await serviceUtil.request('user.GetById', { id });
}
}
复制代码
运行一下
总结
这里的封装还非常的简陋,各位大佬多多指教