记录遇到的问题
P1
配置云开发环境
从头开始设置云开发的方式
- 首先构建一个普通的不使用云的项目
- 然后在项目根目录创建一个miniprogram文件夹和一个cloudfunctions文件夹
- 把除了project.config.json和cloudfunctions文件夹的其他东西都扔到miniprogram文件夹里
- 在project.config.json里添加如下配置
"cloudfunctionRoot":"cloudfunctions/","miniprogramRoot":"miniprogram/"
- 在
app.js
里添加云环境初始化参数
if(!wx.cloud){
console.log("cloud initialize error")
}else{
wx.cloud.init({
env:"xly-t7lma",
traceUser:true
})
}
这时候云函数文件夹会有一朵小云彩,如下,但我曾经有一次配置完成后没发现变成云彩,要么是文件名配置出错,实在没错就把项目删了重新建一个项目
编写云函数时配置云函数运行环境
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
安装got库
直接在package.json里加一个"got": "9.2.2",
,然后npm install
就可以了
注意这里不能写"got": "latest"
,因为服务端的nodejs版本是8.9,会不兼容报错
删除云端函数
当本地写了一个函数然后上传之后,在云端把这个函数进行删除。再次上传这个函数会报错
这需要先同步云函数
然后就可以上传了
post实验报错
感觉这个跟网络有关,有时候能成功,
如下
有时候就失败,如下
需要配置
上传云函数报错
上传云函数遇到莫名错误信息,请帮忙看看
应该是腾讯服务器崩了,过会儿就好了
云函数依赖的包
经过实验可知
如果A函数依赖module M,B函数依赖module M,二者同时完整上传,那这两个包是相互独立互不干扰的。就是说即使A函数完整上传了Module M,B函数如果没有完整上传也是无法调用M包的。
但云端好像内置wx-server-sdk
,这个除外
P2
got包抽风,无法进行实验,摸爬滚打,用云调用解决了
security.msgSecCheck是服务器端API,服务器端API的定义在文档里的描述为
小程序还提供了一系列在后端服务器使用 HTTPS 请求调用的 API,帮助开发者在后台完成各类数据分析、管理和查询等操作。如 getAccessToken,code2Session 等。详细介绍请参考 API 文档。
请求参数说明
对于 GET 请求,请求参数应以 QueryString 的形式写在 URL 中。
对于 POST 请求,部分参数需以 QueryString 的形式写在 URL 中(一般只有 access_token,如有额外参数会在文档里的 URL 中体现),其他参数如无特殊说明均以 JSON 字符串格式写在 POST 请求的 body 中。
而对应的小程序端API指的就是小程序本身可以实现的API
而云调用,我个人理解就是在云函数里调用服务端API
云调用的配置方法
首先在云函数文件夹下面新建config.json
并填写如下内容,意思就是允许使用这个云调用接口
{
"permissions": {
"openapi": [
"security.msgSecCheck"
]
}
}
然后查看这个接口的云调用方法
所以传入方法为
let checkResponse = await cloud.openapi.security.msgSecCheck({
content: text
});
console.log(checkResponse)
return checkResponse;
我一度纳闷传入的为啥是{...}
是个object,反正就记住吧
并且文档说了,云调用的情况下,文字部分正常会返回object,否则会抛出异常,所以要try catch
try{
let checkResponse = await cloud.openapi.security.msgSecCheck({
content: event.text
});
console.log(checkResponse)
return checkResponse;
}catch(err){
return {'errCode':err.errCode,'errMsg':err.errMsg}
}
如果有问题,返回的就如下所示
P3
小函数调用腾讯云SDK
各种找不着,各种对不上,非得去GitHub上找
先是找腾讯云的秘钥
然后找image-node-sdk
文档 链接
const fs = require('fs');
const path = require('path');
const {
ImageClient
} = require('image-node-sdk');
let AppId = ''; // 腾讯云 AppId
let SecretId = ''; // 腾讯云 SecretId
let SecretKey = ''; // 腾讯云 SecretKey
let imgClient = new ImageClient({ AppId, SecretId, SecretKey });
imgClient.ocrIdCard({
formData: {
card_type: 0,
image: fs.createReadStream(path.join(__dirname, './idcard.jpg'))
},
headers: {
'content-type': 'multipart/form-data'
}
}).then((result) => {
console.log(result.body)
}).catch((e) => {
console.log(e);
});
其中__dirname
代表的是本文件所在的路径
P4
tcb-router
版本如下
"dependencies": {
"tcb-router": "1.1.2",
"wx-server-sdk": "latest"
}
视频中老师说,如果当前作用域里没有对应的变量,会到上一个作用域里寻找,例如下面的event,这让我想起了this
,也就是说箭头函数不会覆盖this
变量,但其他函数会覆盖,所以导致了他指向的对象发生了改变
exports.main = async (event, context) => {
const app=new TcbRouter({event});
app.user(async(ctx,next)=>{
ctx.data={};
ctx.data.openId=event.userInfo.openId
})
return }
实验跑通了,讲一下这一章讲的是什么意思吧
由于每个小程序的对应的单个云环境只允许有20个云函数,那如何希望有多个函数呢,要使用TCBROUTER
// 云函数入口文件
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router')
cloud.init({
env: cloud.DYNAMIC_CURRENT_EVN
})
// 云函数入口函数
exports.main = async(event, context) => {
const app = new TcbRouter({
event
});
app.use(async(ctx, next) => {
// 这个是全局中间件,所有调用都要走这个函数
console.log("进入全局的中间件")
ctx.data = {};
ctx.data.openId = event.userInfo.openId;
await next();
})
app.router(['user','school'],async(ctx,next)=>{
// 这个是数组中间件,如果调用了数组中提到的url,那么这个函数就要执行
console.log("arrs middleware");
ctx.data.from='小程序云函数实战';
await next();
})
app.router('user',async(ctx,next)=>{
// 这个是单个的中间件,如果调用了user,那么就会执行这个函数
ctx.data.name="zxy";
ctx.data.role='developer';
await next();//这个next函数指的就是下面的这个async(ctx)函数,这一句话代表着要执行下面这个函数
},async(ctx)=>{
// 这个里面没有next,因为这是最后一个函数了,后续没有其他函数了
ctx.data.nickname='dom';
ctx.body={code:0,data:ctx.data};
})
app.router('school', async (ctx, next) => {
ctx.data.name = "txcloud acdamic";
ctx.data.url = 'cloud.tencent.com';
await next();
}, async (ctx) => {
ctx.data.nickname = '学院sama';
ctx.body = { code: 0, data: ctx.data };
})
return app.serve();
}
本地调用云函数如下,假如说要调用user了,那么云函数的执行逻辑就是:1.先执行app.use
这个全局路由。2.然后当执行到await next()
的时候,意思就是要执行下一个路由了。3.由于请求的url是user,因此要进入那个数组路由,所以全局路由里的await next()
就是在执行数组路由。4.之后以此类推
最终返回的实际上就是那个app.serve
返回的就是ctx对象
user:function(res){
console.log("call user")
wx.cloud.callFunction({
// 要调用的云函数名称
name: "tcbRouter",
// 传递给云函数的参数
data: {
$url: "user", // 要调用的路由的路径,传入准确路径或者通配符*
}
}).then(res => {
console.log(res)
})
},
school: function (res) {
console.log("call school");
wx.cloud.callFunction({
// 要调用的云函数名称
name: "tcbRouter",
// 传递给云函数的参数
data: {
$url: "school", // 要调用的路由的路径,传入准确路径或者通配符*
}
}).then(res=>{
console.log(res)
})
},
按这种方式,我们就可以在一个router云函数里,通过提交不同的url申请,去执行不同的的函数了
临时复习,点击按钮传入数据怎么做
<button bindtap="school" data-aaa="aaa">school</button>
然后再dataset
里找
P5
微信小程序的模板功能升级为订阅信息功能
小程序订阅消息
同样,视频里使用的是GOT包,而这个包调用服务端API会报错,所以我改为云调用
下面是申请订阅信息权限的绑定函数,这个requestSubscribeMessage
只能通过点击发起,用户通过点击允许发送订阅信息一次,小程序就能回复一次订阅信息,如果只允许了1次,并且已经发送一次订阅信息了,再次就不能发送了。
getSubscript:function(event){
console.log('getSubscript')
wx.requestSubscribeMessage({
tmplIds: ['dPgbXjkXrHATlYcPFGc3EA7LpkEnuPD26rkhPctqI0c'],
success: res => {
console.log(res)
},
fail: res => {
console.log(res)
}
})
},
//config.json
{
"permissions": {
"openapi": [
"subscribeMessage.send"
]
}
}
exports.main = async(event, context) => {
try {
console.log(cloud.getWXContext().OPENID)
const result = await cloud.openapi.subscribeMessage.send({
touser: cloud.getWXContext().OPENID, // 通过 getWXContext 获取 OPENID
templateId: 'dPgbXjkXrHATlYcPFGc3EA7LpkEnuPD26rkhPctqI0c',
// page: 'pages/index',
data: {
thing1: {
value: '测试签到'
},
number3: {
value: 47
},
time5: {
value: '2015年01月05日 12:30'
},
phrase6: {
value: '活动'
}
},
emphasisKeyword: 'phrase6.DATA',
miniprogramState: 'developer'
})
// result 结构
// { errCode: 0, errMsg: 'openapi.templateMessage.send:ok' }
return result
} catch (err) {
// 错误处理
// err.errCode !== 0
return {errcode:err.errCode}
}
}
手机上可以看到
P6
wx.cloud.init({traceUser:true})
就代表着云开发自动会接入用户认证部分