小程序云开发记录一
一、什么是云开发?
微信官方云原生开发平台,腾讯云的各种能力加持,用云开发开发者可以节省大量的开发时间和运维成本。
二、云开发优势
无需运维,数据变大不需要管理,
弹性伸缩,业务量变大,服务器的性能也会弹性伸缩。
数据安全:独立的环境
三、云开发基础能力
云函数:云函数=小程序后端
云数据库:json数据库
云存储:文件上传下载
云调用:调用腾讯云的开放接口
HTTP API:原有的项目和云开发小程序打通
四、如何开通小程序云开发
点击微信开发者工具上面的云开发,然后配置环境。
- cloudFunctions | test表示当前的云开发环境是test。
- cloud Functions表示的是云函数的文件夹
- miniprogram表示的是小程序前端的代码
- if(!wx.cloud)表示判断当前的小程序是否支持云开发
- traceUser表示开启访客记录
- app.json表示当前项目的全局配置文件
- app.wxss表示全局的样式
- project.config.json表示项目的全局配置文件
- README.md小程序的说明文件
- miniprogramroot,小程序前端部分的代码
- cloud function root ,云开发中云函数的路径
五、小程序项目初始化
在app.json中输入页面的路径。
“pages/playlist/playlist”,
“pages/blog/blog”,
“pages/profile/profile”
同时在文件目录中会自动生成文件夹。
- tabBar中配置color表示未选中的tabbar的字体颜色,selectedColor表示已经选中的颜色。
- swiper遍历的时候使用block进行遍历,不会将block渲染到里面去。
- interval表示间隔的时间
- duration表示动画执行的时间。
<swiper indicator-dots="true" autoplay="true" interval="4000" duration="2000">
<block wx:for="{{urlList}}">
<swiper-item>
<image src="" mode="widthFit"></image>
</swiper-item>
</block>
</swiper>
六、组件化开发
组件:在用户界面开发领域,组件是一种面向用户的、独立的、可复用的交互元素的封装。
组件化开发的意义:
- 组件化是对实现的分层,更有效的代码组合方式
- 对资源的重组和优化,从而使项目资源管理更合理。
- 组件化有利于单元测试
- 对重构较友好
设计原则
- 高内聚
- 低耦合
- 单一职责
- 避免过多参数
项目中多处都是需要组建开发的。
七、wx:for中的一些知识
- wx:for表示遍历一个数组,wx:for-item="data"表示更换默认的遍历对象名称。
- wx:for-index="idx"表示更换默认索引的名称。
- wx:key="*this"表示
- wx:key=“id” 这里不需要写花括号
八、小程序异步操作解决方案
- 什么是异步?
同步:烧水,水开了之后,继续切菜。
异步:边烧水,边切菜。 - js是单线程的,在同一时间只能处理一个任务。
- callback hell回调地狱
上面的代码表示的是分别读取3个txt文件,然后输出a,b,c,
简单来说,异步编程就是在执行一个指令之后不是马上得到结果,而是继续执行后面的指令,等到特定的事件触发后,才得到结果
也正是因为这样,我们常常会说: JavaScript 是由事件驱动的
现在我们有个需求,a文件读完了再读b,b读完了再读c:
我们可以这样写:
fs.readFile('a.txt','utf8',function(error,data){
if(error){
return console.log('读取数据失败!');
}
console.log('a');
fs.readFile('b.txt','utf8',function(error,data){
if(error){
return console.log('读取数据失败!');
}
console.log('b');
fs.readFile('c.txt','utf8',function(error,data){
if(error){
return console.log('读取数据失败!');
}
console.log('c');
});
});
});
这样就保证了 a 读取完在读 b,b读取完在读 c 了
上面这种代码的书写方式其实就是 回调地狱,一层套一层,维护起来及其困难,如果有100个文件怎么办?
使用 Promise 解决回调地狱问题
Promise Es6的语法
- 三种状态
1.pending 初始状态 待定的
2.fulfilled。成功状态
3.rejected。失败状态 - 以上状态是不可逆的
使用Promise解决回调地狱问题
new Promise((resolve, reject) => {
setTimeout(() => {
console.log(1)
resolve()//执行成功之后要执行的
}, 1000)
}).then((res)=>{
setTimeout(() => {
console.log(2)
}, 2000);
})
Promise的两个重要的函数
一、Promise.all 场景,上传完所有图片返回文件ID之后再保存
let p2=new Promise((resolve,reject)=>{
setTimeout(() => {
console.log('p2')
resolve('p2')
}, 1000);
})
let p1=new Promise((resolve,reject)=>{
setTimeout(() => {
console.log('p1')
// resolve('p1')
reject('p1')
}, 2000);
})
let p3=new Promise((resolve,reject)=>{
setTimeout(() => {
console.log('p3')
resolve('p3')
}, 3000);
})
Promise.all([p1,p2,p3]).then((res)=>{
console.log('全部完成')
console.log(res)
}).catch((err)=>{
console.log('失败')
console.log(err)
})
全部执行成功输出
p2
p1
p3
全部完成
[“p1”, “p2”, “p3”]
p1执行失败输出
p2
p1
失败
p1
p3
Promise.all中,只要有一个任务是失败的,整个任务就都是失败的,但它并不会阻止其他任务的执行
== demo.js? [sm]:57 p1 表示在代码的57行输出p1==
二、Promise.race 比赛、竞赛,场景,可以判断请求是否超时
Promise.race([p1,p2,p3]).then((res)=>{
console.log('完成')
console.log(res)
}).catch((err)=>{
console.log('失败')
console.log(err)
})
按照上面的方法执行之后,输出:
p2
完成
p2
p1
p3
九、 async await 异步解决方法 Es7语法
在onLoad方法中调用foo方法
async foo(){
console.log('foo')
let res = await this.timeout()
console.log(res)
},
timeout(){
return new Promise((resolve,reject)=>{
setTimeout(() => {
console.log(1)
resolve('resolved')
}, 1000);
})
}
输出结果:
foo
1
resolved
- await关键字一定要使用在async当中,没有async的话,await也没有用。
只要有一个任务是完成的,最后的结果就是完成的,也不会影响其他任务继续执行
十、使用云函数调用接口并保存返回数据
- 创建云函数
右键选择cloudfunctions,新建Node.js云函数,输入函数的名称 - 要想请求其他接口,需要使用到request- promise,所以需要安装相应的包。在创建的云函数上面右键,在外部终端窗口中打开,然后执行命令(需要提前安装npm):
npm install --save request
npm install --save request-promise
执行完成之后,在云函数的目录中有一个node_modules的文件夹。 - 在index.js中写入代码并在云开发中的数据库中创建集合
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
}) // 使用当前云环境
const db = cloud.database() //数据库的初始化
const rp = require('request-promise')//引入需要的包
const URL = 'http://musicapi.xiecheng.live/personalized'
// 云函数入口函数
exports.main = async (event, context) => {
//通过request- promise请求对应的URL
const playlist = await rp(URL).then((res) => {
return JSON.parse(res).content
})
//db.serverDate获取服务器时间
//...playlist[i]获取到playlist的每一个值 ...表示扩展运算符
for (let i = 0, len = playlist.length; i < len; i++) {
await db.collection('playlist').add({
data: {
...playlist[i],
createTime: db.serverDate(),
}
}).then((res) => {
console.log('插入成功')
}).catch((err) => {
console.error('插入失败')
})
}
}
- 上传并测试云函数
右击云函数文件夹,然后选择上传并部署:云端安装依赖,等待云函数上传完毕。点击云开发=>云函数,找到对应的函数点击云端测试,如果需要参数的话就加入参数,然后点击运行测试。
十一、小程序添加编译模式对单独页面进行调试
- 点击普通编译模式
- 选择添加编译模式
- 输入编译模式,参数等一些属性,点击确定即可
- 传参形式nickName=“张三”&avatarUrl=“http://wwerwr.sd.sdf.jpg”
- 注意要编译的页面必须提前在app.json文件中已经配置了路由。
十二、改变小程序默认获取数据库的数据条数为100条限制
const list=await memListCollection.get()
return {
length:list.data.length
}
解决方案
获取总条数,然后根据每次取的条数(最大为100条)分批次取,类似分页取数据。使用limit函数进行获取。
- 获取数据库中数据的总条数
const MAX_LIMIT=100
const total=await memListCollection.count().total//获取总条数
const batchTimes=Math.ceil(total/MAX_LIMIT)//向上取整
const tasks=[]
for(let i=0;i<batchTimes;i++){
let promise=memListCollection.skip(i*MAX_LIMIT).limit(MAX_LIMIT).get()
tasks.push(promise)
}
let list={
data:[]
}
if(tasks.length>0){
//reduce 表示累加操作,previousValue,currentValue
list = (await Promise.all(tasks)).reduce((acc,cur)=>{
return{
data:acc.data.concat(cur.data)
}
})
}
十三、定时触发调用执行函数
在此云函数中的config.json文件中进行配置
此触发器表示的是每天的10,14,16,23点执行此云函数。
{
"triggers":[
{
"name":"myTrigger",
"type":"timer",
"config":"0 0 10,14,16,23 * * * *"
}
]
}
配置完成之后在该云函数上右键然后点击上传云函数。
有的一些云函数的执行时间比较长,或者是因为网络的原因,执行的比较慢,可以在云函数中配置超时时间。防止因为超时时间设置的比较短而出现错误。