为何在如何创建微信小程序序开发工具中,开通云开发功能,提升加载数据错误?

9 月 11 日,微信开发者工具新增小程序「云开发」功能。大多数开发者在开发应用时和部署服务时,无论是选择公有云还是自建数据中心,都需要提前考虑服务器、存储和数据库等需求,并且会花费时间精力在部署应用、依赖上。而通过「小程序·云开发」,开发者可以开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力,实现小程序的快速上线和迭代。「小程序·云开发」将以服务的方式为开发者提供如云函数、数据库、存储管理等所需功能,大大降低了小程序的开发门槛,仅需通过「小程序·云开发」提供的接口,就能实现因缺乏后端知识而无法实现的需求。什么是云开发?那么什么是云开发呢?云开发为开发者提供完整的云端支持,弱化了后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。从开发流程来看,以往开发一个微信小程序需要经过产品功能构思、模块划分、原型设计、UI 设计、前端开发、后端开发、接口联调、测试上线等开发阶段。有了「小程序·云开发」后,前端工程师将可以独立实现前端开发、后端开发、接口联调工作,且无需太多后端知识。不同于腾讯云提供的虚拟机级别的服务,「小程序·云开发」是应用级别的服务平台,开发者无需编写后端代码,调用云开发提供的接口即可。目前上线的「小程序·云开发」服务提供了三大基础能力支持: 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码。
数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库。
文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理。 为了便于管理云开发资源,微信还为开发者提供了云开发控制台,可以实现查看小程序用户信息、管理数据库、云函数统计分析等功能。总结来说,「小程序·云开发」具有以下特点: 提供完整后端服务解决方案,包括数据库、静态资源管理和云函数(功能服务)
背靠腾讯云大平台,腾讯云丰富的 API 和功能都可以简单调用
对于普通开发者,完全免费
对于高级服务型小程序,提供更强服务支持、计费弹性、不使用不计费的特点
无服务器搭建,无域名配置,直接调用 API 使用 而对于小程序开发新手来说,小程序·云开发更是个不错的练手平台。
更多「小程序·云开发」的详细介绍:https://developers.weixin.qq.com/minigame/dev/wxcloud/basis/getting-started.html
如何调用「小程序 · 云开发」「小程序·云开发」上手十分简单,开发者安装测试版本的开发者工具后即可进行开发。接下来我们将为大家讲解如何使用小程序云进行开发。
(下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html#wechat_redirect)
如果是没有开通「小程序·云开发」的账号,首次点击「云开发」会出现下面的界面,该界面主要是「小程序·云开发」的介绍和开通入口。点击蓝色的**「开通」**按钮进入创建小程序云流程。在「新建环境」中,目前暂时只提供基础版套餐。填写上「环境名称」后会自动生成「环境 ID」,点击「确定」后,会使用小程序开发账号在腾讯云开通一个 fake account。到此小程序云就开通了。「小程序 · 云开发」可以在小程序中直接通过调用 wx.cloud.* 的方式进行调用。不过在调用小程序云 API 之前,需要先调用 wx.cloud.init 对其进行初始化:wx.cloud.init({
env: 'tianqi-xxx'
})
使用上面的代码实现初始化时,需要传入 env 参数,该参数为创建小程序云时的环境 ID,可以在「云开发控制台」中找到:「小程序·云开发」实战教程在上文中,我们介绍了如何调用「小程序·云开发」,而这只是最基础的一步。如果想要真正入门开发微信小程序,还有众多问题亟待解答:在这里,我们为大家推荐2个学习了解「小程序·云开发」的途径:第一个教程点击链接即可获取:https://github.com/TencentCloudBase/mp-book这个教程涵盖以下几大内容:功能介绍 + 文档导读(相当于基础教程) + 基础场景的开发实例(中高级教程),可以帮助对云开发感兴趣的同学快速上手,其中也有一些基础场景的代码可以直接学习拷贝。第二个途径可以在腾讯云学院新上线的好课《从 0 到 1 实现天气查询小程序》中找到答案,学习课程后开发者将可以独立从零开始完成并上线一个小程序。课程内容以打造一款拥有天气预报和签到功能的小程序为主线,从基础知识到小程序运行机制,从开发环境搭建到「小程序·云开发」的接口使用、调试、上线,打通微信小程序开发全流程。这份实战课程由浅入深,从介绍微信小程序、小程序云的开发基础知识,到小程序调试技巧和上线发布,详细讲授了一个微信小程序如何诞生,并鼓励学习者去创新与创造。课程上线后,也收到了不少学习者的好评,对于新手而言课程难度也十分适当。课程学习方式无论你是小程序开发工程师,还是小程序开发爱好者,《从 0 到 1 实现天气查询微信小程序》都是你学习「小程序·云开发」的不二选择,通过以下方式即可报名参与课程:PC 端访问链接即可报名 ?https://cloud.tencent.com/developer/edu/course-1245手机端扫码报名即可 ?
了解更多小程序开发相关内容,欢迎微信扫描下方二维码关注微信极客WeGeek公众号,共筑微信生态。
}
前言
微信小程序开发了云开发的功能, 提供了数据库、云函数、储存空间的服务。在此基础上,基本可以用js一把捞一个相对完整的服务,并且省下了发布、部署、运维的繁琐。
优点
语言同构、js一把捞, 对前端开发非常友好, 使用js就可以完成整个业务流程。
环境整合的非常好, 不用操心各种环境配置、数据库、存储空间、部署、运维的东西,减轻了开发复旦
自带登录和账号体系,方便接入
缺点
过多的回调、异步导致代码难看切难以维护、难以调试。
云函数的框架过于简陋, 处理复杂业务的时候对代码组织能力要求很高
数据库多表联查的时候很忧伤, 严重影响性能
没有公共代码块, 无法共享通用代码, 难以整合组织代码
产品需求经过考虑决定做一个小号的微博小程序, 梳理的功能如下后台部分根据官方的api文档, 小程序的云函数也是可以通过http调用的,这就给一个独立的后台提供了技术接口。 我们可以通过http调用小程序云函数来读取和操作数据库来实现产品后台的功能,是否可以通过htpps上传图片还待探索用户部分用户端的就是一个小号的微博了。 其中,微信提供了一个存储空间,可以方便的进行文件的存储,账号部分可以直接通过微信的鉴权机制,使用openid作为用户id。原型设计不多说, 上设计稿。 开发环境
其实上面的都不重要,坑都在这里
1.更新开发工具, 摆脱回调这里要分两部分说小程序部分 在最新的微信开发工具中, 开发了增强编译的功能, 已经支持async语法了。使用async的好处这里就不在列举了。为了可以使用async来调用微信原生的api。可以引入一个工具, 将回调式的转化为async方式function promisify (api) {
return (options, ...params) => {
return new Promise((resolve, reject) => {
api(Object.assign({}, options, { success: resolve, fail: reject }), ...params);
});
}
}
复制代码// 这样就可以简化微信原生的api
const getSetting = promisify(wx.getSetting)
const res = await getSetting()
复制代码但是async 语法也有不好的地方在于异常捕获写起来很难看, 越是复杂的逻辑, 用户捕获异常的catch就越不好处理, 这里可以使用await-to-js来进一步优化import to from 'await-to-js'
// 使用node风格的异常捕获
const [err, res] = await to(getSetting())
复制代码云函数部分 云函数是一个纯净的node环境, 使用的时候要注意它不支持import语法,在导入的时候需要使用require 例如 const to = require('await-to-js').default; 2.使用字体图标代替切图小程序推荐使用rpx作为尺寸单位, 切图适配的时候, 小图标可能会在缩放的时候失真,推荐使用字体图标。将制作好的字体图标放入小程序的css文件中就好了,我这里是用的阿里icon的图标库, 将base64的css样式直接放在全局的css中 3.开发工具。微信开发工具自带了编译和无法替代的云开发工具, 目前是没有办法摆脱它了。 但是在编辑代码的时候还是可以用其他工具的。可以用vscode作为代码编辑攻击, 安装minapp等插件。微信开发工具作为预览和调试的工具就好4.npm支持,debuger在云函数中是支持直接使用npm包的, 但是每一个云函数的入口对应一个文件夹, 每一个文件夹需要单独npm。为了可以在本地断点调试云函数,我们必须在云函数下的每一个文件夹install一下。这操作是真的难受。。。 在开发工具中, 右键云函数文件夹可以开启本地调试, 然后就可以在浏览器中打断点了, 同时, console页面也可以看到云函数的console信息, 注意右边可以切换请求方式。
代码组织先放一下数据库的方案 前文说过, 云函数每一个文件夹视为一个入口文件,并且需要单独install一下。 我们最少需要4张表,最起码的增删改查就需要16个接口, 一个接口一个入口显然不可能, 所以我们可能需要自己做一下路由的设计。 考虑到代码的复用, 我将每一个入口作为一个功能块, 将代码的功能拆分成service层、router层、controller层. 在小程序调用云函数的时候传入action字符串作为路由的参数。将对数据库的操作细化,作为service便于复用。 在controller里调用service来处理复杂逻辑。1.根据数据库操作编写service// user/user.js
// UserBase 确定每个集合的数据结构
class UserBase {
constructor(data) {
this.openId = data.openId
this.avatarUrl = data.avatarUrl
this.city = data.city
this.country = data.country
this.gender = data.gender
this.language = data.language
this.nickName = data.nickName
this.province = data.province
this.signature = null // 签名
this.watchList = [] // 关注列表
this.releaseList = [] // 发布列表
this.createTime = db.serverDate()
this.userStatus = 0 // 用户状态 0 正常 1 限制登录
this.inviteUser = null
}
}
复制代码// 这里用来实现对数据库的操作
class User {
// 获取用户信息
async getUserInfo(openId) {
const [err, {data}] = await to(db.collection('user')
.where({ openId: openId })
.get())
if (err) return Promise.reject(err.errMsg)
if (Array.isArray(data) && data.length) return data[0]
else return null
}
// 创建新用户
async createUser (userInfo) {
let [err, res] = await to(db.collection('user').add({ data: new UserBase(userInfo)}))
if (err) return Promise.reject(err.errMsg)
return res._id
}
}
复制代码2.根据需求调用service的方法, 实现业务Controller可以通过继承也可以单独引入进来运行// user/userController.js 这里调用service来处理复杂逻辑
// 根据情况也会调用其他的模块, 这个时候就用callFunction
// 云函数入口文件
const User = require('./user.js')
const cloud = require('wx-server-sdk')
cloud.init({ env: 'prod-4ygqk'})
const to = require('await-to-js').default;
class UserController extends User {
// 处理登录
async handelLogin(event) {
const { OPENID } = event
const [err, res] = await to(this.getUserInfo(OPENID))
if (err) return {err, res}
if (res) return {err, res}
if (!event.loginInfo) {
return {err: '注册用户失败,请先调用wx.userInfo接口', res}
}
event.loginInfo.openId = OPENID
return this.handelCreateUser(event)
}
// 注册用户
async handelCreateUser(event) {
const { loginInfo, OPENID } = event
const [err, res] = await to(this.createUser(loginInfo))
if (err) return {err, res}
const [_err, _res] = await to(this.getUserInfo(OPENID))
if (_err) return {err, res: _res}
return {err, res: _res}
}
// 通过openId查询用户
async queryUserByOpenid(event) {
const { targetUser, OPENID} = event
// 如果没有传openId进来, 就查询当前用户
const seatchOpenId = targetUser
OPENID
const [err, res] = await to(this.getUserInfo(seatchOpenId))
if (err) return {err, res}
// 查询是否关注过该用户
if (res && targetUser) {
const [error,{result}] = await to(cloud.callFunction({
name: 'attention',
data: {
action: 'queryIsAttention',
currentUser: OPENID,
targetUser: targetUser
}
}))
if (error) return {err: error, res: result}
res.isAttention = result.res
}
return {
res: res,
err: null
}
}
}
module.exports = UserController
复制代码3.根据路由指派控制器这里我们将openId作为用户识别码挂载在event上, 供控制器使用 在Controller需要调用其他模块的Controller时, 也将所需的参数挂载在event上。 这里的event实际上就是这次请求的上下文// 云函数入口文件 user/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: 'prod-4ygqk'})
const UserController = require('./userController.js')
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
const { OPENID, APPID } = wxContext
event.OPENID = OPENID
const user = new UserController()
const { action } = event
switch (action) {
case 'login': {
return user.handelLogin(event)
};
case 'createUser': {
return user.handelCreateUser(event)
};
case 'queryUserByOpenid': {
return user.queryUserByOpenid(event)
};
}
}
复制代码4.其他复杂情况需要调用其他模块的async queryArticlebyId(event) {
const { OPENID, id } = event
// 查询对应的文章内容
let [err, res] = await to(article.queryArticlebyId(id))
// 有错误返回错误, 没有查到返回空
if (err) return {err, res}
if (!res) return {err, res}
// 查询文章用户, 调用user模块
const [error, { result }] = await to(cloud.callFunction({
name: 'user',
data: {
action: 'queryUserByOpenid',
currentUser: event.OPENID,
targetUser: res.openId
}
}))
// 调用userInfo错误
if (error) return {err: error, res}
// userInfo自己的错误
if (result.err) return {err: result.err, res: res}
res.user = result.res
// 查询用户是否已经收藏, 调用收藏模块
const [collectionErr, collectionRes] = await to(article.queryIsCollection(OPENID, id))
res.isCollection = collectionRes
return {res, err: null}
}
复制代码需要异步循环的异步迭代一直是一个问题。一方面涉及到并发和效率, 另一方面又涉及到异常处理。 如果按照线性的async方式查询会严重的影响到速度。 所以必须使用Promise.all的方式。 以下代码缺少异常处理 async queryArticleAll(event) {
const { userInfo, size = 10, page, sort = 'desc', orderBy = 'createTime' } = event
let ArticleList = await article.queryArticleAll({ size, page, sort, orderBy })
if (ArticleList.length === 0) {
return []
}
const funList = ArticleList.map(async article => {
// 查询文章的作者
const [err,{result}] = await to(cloud.callFunction({
name: 'userInfo',
data: {
action: 'queryUserByOpenid',
currentUser: event.OPENID,
targetUser: article.openId
}
}))
let user = result.res
null
article.user = user
return article
})
return {res: await Promise.all(funList), err: null}
}
复制代码最后其他就没有啥子东西可写了。后面使用http调用云函数的以后再继续尝试。 在调试云函数的时候几乎花掉了全部的耐心....最后贴代码和地址https://github.com/xanggang/picture-miniapp
复制代码最近微信关闭了改名的通道, 暂时改不了名字和头像了... }

我要回帖

更多关于 如何创建微信小程序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信