1.引入
最近在搞小程序,采用的是微信云开发云函数作为后端,云函数是nodejs开发,但是因为不是很会nodejs,导致遇到一个印象深刻的bug与知识点,在此记录下来。
知识点比较浅显,大佬看了的话见笑了,这里更多是做个笔记
2.需求举例
集合中有category与items,如下
category
items
需要通过用户输入的cname字段找出属于此类的项,如上:通过用户输入的美食找出宫保鸡丁、回锅肉、鱼香肉丝返回给前端。
3.错误例子
- 代码
前端
index.wxml
<view class="btnview">
<button type="primary" bindtap="callFunc">获取美食类别下的美食</button>
</view>
index.js
Page({
callFunc:function(){
wx.cloud.callFunction({
name: 'quickstartFunctions',
data: {
type: 'index/index',
cname:'美食'
}
}).then((res) => {
console.log(res)
})
}
})
云函数
const cloud = require('wx-server-sdk');
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
});
const db = cloud.database();
/*
1.通过 cname参数查询category集合中的cid
2.再通过获取的cid查询items下属于该类别的项
3.返回获取该类别的项
*/
exports.main = async (event, context) => {
var cname = event.cname;
return await db.collection('category').where({
cname:cname
}).get().then(res=>{
console.log(res)
db.collection('items').where({
cid:res.data[0]._id
}).get().then(res=>{
console.log(res)
return res // 返回查找所属cname的项
});
});
};
- 运行结果
云函数:
前端:
通过前端的输出发现,虽然云函数查找到了所属美食的项并且写了return这查找的列表代码,但是前端输出的确实undefined,经过排查,发现是云函数的代码问题
4.分析错误
db.collection…查询数据库是异步操作,虽然如上代码云函数前有return await,但是这里是两个db操作,发生了两次异步,而只await了一次
await只会等待红色框的异步操作,而青色框内的异步操作则不会等待,程序运行到青色的db时会跳过直接运行接下来的代码,而接下来没有代码了,所以会直接返回,而不会等待青色框内的异步return结果,所以前端得到的结果是undefined
5.尝试解决方法
既然不会等待青色框的异步,那么我想着在db前加上await,结果是代码编译报错,这样的写法是错误的
6.解决方法、代码及结果
- 解决方法,在CSDN网站搜索相关知识点后,得知await只能在声明了async的function中才有效,那么只好用function封装一下或者在then的作用域内用async声明才可以使用await
- 代码
方式一:另写一个function
const cloud = require('wx-server-sdk');
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
});
const db = cloud.database();
/*
1.通过 cname参数查询category集合中的cid
2.再通过获取的cid查询items下属于该类别的项
3.返回获取该类别的项
*/
exports.main = async (event, context) => {
var cname = event.cname;
return await
db.collection('category').where({
cname:cname
}).get().then(res=>{
console.log(res)
return getItems(res)
});
};
// await 只能用在声明了async的函数中
async function getItems(res){
return await db.collection('items').where({
cid:res.data[0]._id
}).get().then(res=>{
console.log(res)
return res // 返回查找所属cname的项
});
}
方式二:在then的作用域内用async声明
const cloud = require('wx-server-sdk');
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
});
const db = cloud.database();
/*
1.通过 cname参数查询category集合中的cid
2.再通过获取的cid查询items下属于该类别的项
3.返回获取该类别的项
*/
exports.main = async (event, context) => {
var cname = event.cname;
return await
db.collection('category').where({
cname:cname
}).get().then(async(res)=>{ // 声明async
console.log(res)
// 这样写法,代码较紧凑和乱
return await db.collection('items').where({
cid:res.data[0]._id
}).get().then(res=>{
console.log(res)
return res // 返回查找所属cname的项
});
});
};
3.这样写后,前端能得到正确数据了
6.后记
- 这是我个人的写法,可能不太正确,如果有更好的方法欢迎指导
- 简单的笔记
个人认为
声明了async的function,在里面可以执行同步或异步代码,异步代码可以用await变成同步代码.
await只能使用在async声明的函数里,不能使用在普通函数里。
参考BLOG链接:CSDNBLog:async、await个人使用理解