微信小程序异步转同步的解决方法
异步转同步的解决方案一、前言二、 promise的概念三、promise的使用四、一个因为异步请求出问题的案例五、案例的解决方案1、运用promise解决异步转同步问题2、运用async+await+promise解决异步转同步问题为什么有Async/Await?什么是`async/await`呢?什么是Async什么是await案例解决一、前言简单阐述一个困扰我们已久的问题:因为异步函数中的赋
一、前言
简单阐述一个困扰我们已久的问题:因为异步函数中的赋值操作是不同步的(即程序不会等该函数执行完再执行下面的函数),这样就导致了在该异步函数下面的程序的赋值操作会先执行,这样就导致了赋值操作后的值为undefined。
二、 promise的概念
promise是一个对象,简单来说就是会保存一个异步操作的结果。
new Promise((resolve,reject)=>{
//自定义的异步函数
});
看到定义的Promise有两个参数,resolve
和reject
:
resolve
:将异步的执行从pending(请求)
变成了resolve(成功返回)
,是个函数执行返回。reject
:顾名思义“拒绝”,就是从请求变成了"失败",是个函数可以执行返回一个结果,但我们这里推荐大家返回一个错误new Error()
。
简答来说resolve是自定义成功的返回,reject是自定义失败的返回,下面给个例子:
new Promise((resolve,reject)=>{
wx.request({
url:"localhost:8080/test",
success(res){
//调用成功返回回调的信息
resolve(res)
},fail(err){
//调用失败返回错误信息
reject(err)
}
})
})
三、promise的使用
一般的我们会把它封装在一个函数里,在函数里面返回promise,将上面的函数进行封装
myrequest(){
return new Promise((resolve,reject)=>{
wx.request({
url:"localhost:8080/test",
success(res){
//调用成功返回回调的信息
resolve(res)
},fail(err){
//调用失败返回错误信息
reject(err)
}
})
})
}
我们通过Promise的原型方法then
拿到我们的返回值
myrequest().then((res)=>{
console.log(res)
})
用catch
捕获出错的返回值
myrequest().then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err)
})
四、一个因为异步请求出问题的案例
下面是一个以微信小程序业务为例子的程序,这里面的大致流程和意思就是想在onLaunch函数里面调用openid然后再获取用户信息,然后经过socketopen判断是否进行websocket连接,然后进行websocket监听。
App({
globalData: {
userInfo: null,
openid: "",
canIUse: wx.canIUse("button.open-type.getUserInfo"),
host: "http://119.29.196.165:8081",
chathost: "ws://localhost:8000/imserver/",
SocketTask: "",
socketOpen: false,
},
onLaunch(){
this.getopenid();
this.getUserInfo();
this.websocketconnect(this);
this.websocketserver();
}
},
// 获取用户openid
getopenid() {
var that = this;
console.log("going getopenid");
wx.cloud.callFunction({
name: "openapi",
success: function (res) {
that.globalData.openid = res.result.openid;
},
fail: function (res) {
console.log("失败:" + res);
},
});
},
// 获取用户信息
getUserInfo() {
var that = this;
console.log("going getUserInfo");
wx.getSetting({
success: function (res) {
if (res.authSetting["scope.userInfo"]) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo;
},
fail(err) {
console.log(err);
},
});
}
},
fail(err) {
console.log(err)
},
});
},
// 连接websocket服务器
websocketconnect(tha) {
var that = tha;
// 创建Socket
console.log(that.globalData.openid);
that.globalData.SocketTask = wx.connectSocket({
url: "ws://localhost:8000/imserver/" + that.globalData.openid,
data: "data",
header: {
"content-type": "application/json",
},
method: "post",
success: function (res) {
that.globalData.socketOpen = true;
console.log("WebSocket连接创建", res);
},
fail: function (err) {
console.log(err);
},
});
},
// websocket监听
websocketserver() {
var that = this;
that.globalData.SocketTask.onOpen((res) => {
that.globalData.socketOpen = true;
console.log("监听 WebSocket 连接打开事件。", res);
});
that.globalData.SocketTask.onClose((onClose) => {
//如果websocket关闭了 就重新连接
console.log("监听 WebSocket 连接关闭事件。", onClose);
that.globalData.socketOpen = false;
this.websocketconnect(that);
});
that.globalData.SocketTask.onError((onError) => {
console.log("监听 WebSocket 错误。错误信息", onError);
that.globalData.socketOpen = false;
});
that.globalData.SocketTask.onMessage((onMessage) => {
//监听WebSocket接受到服务器的消息事件
console.log(onMessage);
});
},
});
但是会发现,请求getopenid函数是异步的导致下面划红线的地方为空
导致websocketconnect函数请求失败
五、案例的解决方案
1、运用promise解决异步转同步问题
下面运用到then式的链式写法,其本质就是一直往下传递返回一个新的Promise,也就是说then在下一步接收的是上一步返回的Promise,这样就可以是函数执行按照顺序进行了。
App({
globalData: {
userInfo: null,
openid: "",
canIUse: wx.canIUse("button.open-type.getUserInfo"),
host: "http://119.29.196.165:8081",
chathost: "ws://localhost:8000/imserver/",
SocketTask: "",
socketOpen: false,
},
onLaunch(){
this.getopenid()
.then((result)=>{
return this.getUserInfo()
})
.then((result)=>{
return this.websocketconnect(this)
))
.then((result)=>{
return this.websocketserver()
})
//catch是捕获错误异常,原本每一个promise都有一个catch,但是他现在有冒泡特性,所以现在只需要一个就好了
.catch((err)=>{
console.log(err)
})
}
},
// 获取用户openid
getopenid() {
var that = this;
console.log("going getopenid");
return new promise((reslove,reject)=>{
wx.cloud.callFunction({
name: "openapi",
success: function (res) {
that.globalData.openid = res.result.openid;
resolve(that.globalData.openid);
},
fail: function (res) {
console.log("失败:" + res);
reject(res);
},
});
})
},
// 获取用户信息
getUserInfo() {
var that = this;
console.log("going getUserInfo");
return new promise((reslove,reject)=>{
wx.getSetting({
success: function (res) {
if (res.authSetting["scope.userInfo"]) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo;
resolve(that.globalData.userInfo);
},
fail(err) {
console.log(err);
reject(err);
},
});
}
},
fail(err) {
reject(err);
},
});
})
},
// 连接websocket服务器
websocketconnect(tha) {
var that = tha;
// 创建Socket
console.log(that.globalData.openid);
return new promise((reslove,reject)=>{
that.globalData.SocketTask = wx.connectSocket({
//下面是自己在后端搭建的websocket服务器,通过不同的openid来识别并建立连接
url: "ws://localhost:8000/imserver/" + that.globalData.openid,
data: "data",
header: {
"content-type": "application/json",
},
method: "post",
success: function (res) {
that.globalData.socketOpen = true;
console.log("WebSocket连接创建", res);
resolve(res)
},
fail: function (err) {
reject(err)
},
});
})
},
// websocket监听
websocketserver() {
var that = this;
return new promise((reslove,reject)=>{
//下面是后端建立了websocket连接后在socket对象里面提供的监听事件
//websocket打开监听
that.globalData.SocketTask.onOpen((res) => {
that.globalData.socketOpen = true;
console.log("监听 WebSocket 连接打开事件。", res);
});
//websocket关闭监听
that.globalData.SocketTask.onClose((onClose) => {
//如果websocket关闭了 就重新连接
console.log("监听 WebSocket 连接关闭事件。", onClose);
that.globalData.socketOpen = false;
this.websocketconnect(that);
});
//websocket错误监听
that.globalData.SocketTask.onError((onError) => {
console.log("监听 WebSocket 错误。错误信息", onError);
that.globalData.socketOpen = false;
});
//websocket接收到的消息的监听
that.globalData.SocketTask.onMessage((onMessage) => {
//监听WebSocket接受到服务器的消息事件
console.log(onMessage);
});
})
},
});
2、运用async+await+promise解决异步转同步问题
为什么有Async/Await?
我们可以使用promise来解决异步的问题,可以用then的链式表达更清晰,但是我们在发现有大量异步请求的时候,会发现充满屏幕的then,看起来比较吃力,而es7的async和await就是为了解决这种情况
什么是async/await
呢?
async/await是一对好基友,缺一不可,他们的出生是为Promise服务的。可以说async/await是Promise的进化版
什么是Async
async
必须声明的是一个function
async function myrequest(){
}
什么是await
await
就必须是在这个async
声明的函数内部使用,否则就会报错。
async function myrequest(){
await getopenid();
}
请记住await是在等待一个Promise的异步返回,就是等待函数内部需要返回一个promise才能起到效果
async function myrequest(){
await getopenid(){
return new promise((resolve,reject)=>{
})
};
}
运用async/await解决案例
App({
globalData: {
userInfo: null,
openid: "",
canIUse: wx.canIUse("button.open-type.getUserInfo"),
host: "http://119.29.196.165:8081",
chathost: "ws://localhost:8000/imserver/",
SocketTask: "",
socketOpen: false,
},
onLaunch: function () {
this.dowait();
},
async dowait() {
await this.getopenid();
await this.getUserInfo();
await this.websocketconnect(this);
await this.websocketserver();
},
//初始化云服务
cloudinit() {
if (!wx.cloud) {
console.error("请使用 2.2.3 或以上的基础库以使用云能力");
} else {
wx.cloud.init({
// env 参数说明:
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
env: "school-n97ya",
traceUser: true,
});
}
},
// 获取用户openid
getopenid() {
var that = this;
console.log("going getopenid");
return new Promise((resolve, reject) => {
wx.cloud.callFunction({
name: "openapi",
success: function (res) {
that.globalData.openid = res.result.openid;
resolve(that.globalData.openid);
},
fail: function (res) {
console.log("失败:" + res);
reject(res);
},
});
});
},
// 获取用户信息
getUserInfo() {
var that = this;
console.log("going getUserInfo");
return new Promise((resolve, reject) => {
wx.getSetting({
success: function (res) {
if (res.authSetting["scope.userInfo"]) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo;
resolve(that.globalData.userInfo);
},
fail(err) {
console.log(err);
reject(err);
},
});
}
},
fail(err) {
reject(err);
},
});
});
},
// 连接websocket服务器
websocketconnect(tha) {
var that = tha;
// 创建Socket
return new Promise((resolve, reject) => {
console.log(that.globalData.openid);
that.globalData.SocketTask = wx.connectSocket({
url: "ws://localhost:8000/imserver/" + that.globalData.openid,
data: "data",
header: {
"content-type": "application/json",
},
method: "post",
success: function (res) {
that.globalData.socketOpen = true;
console.log("WebSocket连接创建", res);
resolve(res)
},
fail: function (err) {
console.log(err);
reject(err)
},
});
});
},
// websocket监听
websocketserver() {
var that = this;
return new Promise((resolve, reject) => {
that.globalData.SocketTask.onOpen((res) => {
that.globalData.socketOpen = true;
console.log("监听 WebSocket 连接打开事件。", res);
});
that.globalData.SocketTask.onClose((onClose) => {
//如果websocket关闭了 就重新连接
console.log("监听 WebSocket 连接关闭事件。", onClose);
that.globalData.socketOpen = false;
this.websocketconnect(that);
});
that.globalData.SocketTask.onError((onError) => {
console.log("监听 WebSocket 错误。错误信息", onError);
that.globalData.socketOpen = false;
});
that.globalData.SocketTask.onMessage((onMessage) => {
//监听WebSocket接受到服务器的消息事件
console.log(onMessage);
});
});
},
});
更多推荐
所有评论(0)