• 一、前言
  • 二、 promise的概念
  • 三、promise的使用
  • 四、一个因为异步请求出问题的案例
  • 五、案例的解决方案
    • 1、运用promise解决异步转同步问题
    • 2、运用async+await+promise解决异步转同步问题
      • 为什么有Async/Await?
      • 什么是`async/await`呢?
        • 什么是Async
        • 什么是await
      • 运用async/await解决案例

一、前言

​ 简单阐述一个困扰我们已久的问题:因为异步函数中的赋值操作是不同步的(即程序不会等该函数执行完再执行下面的函数),这样就导致了在该异步函数下面的程序的赋值操作会先执行,这样就导致了赋值操作后的值为undefined。

二、 promise的概念

promise是一个对象,简单来说就是会保存一个异步操作的结果。

new Promise((resolve,reject)=>{//自定义的异步函数
});

看到定义的Promise有两个参数,resolvereject:

  • 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();}
},// 获取用户openidgetopenid() {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;// 创建Socketconsole.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)})}
},// 获取用户openidgetopenid() {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;// 创建Socketconsole.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,});}},// 获取用户openidgetopenid() {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;// 创建Socketreturn 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);});});},
});

微信小程序异步转同步的解决方法相关推荐

  1. Taro开发微信小程序遇到的问题和解决方法

    Taro开发微信小程序遇到的问题和解决方法 参考文章: (1)Taro开发微信小程序遇到的问题和解决方法 (2)https://www.cnblogs.com/wuliujun521/p/114753 ...

  2. 如何同步微信信息php,微信小程序中实现同步请求的方法

    本篇文章给大家带来的内容是关于微信小程序中实现同步请求的方法,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 微信小程序默认是用同步请求的,但有些时候需要数据的同步请求,可使用的方法有 ...

  3. 微信小程序Canvas卡顿优化解决方法

    文章目录 一.引入 二.分析问题 三.解决方法 四.解决后效果图 五.绘制好的地图 一.引入 原安卓图书馆选座项目CSDN博客链接: Android图书馆选座系统课程设计 最近在搞微信小程序,想把以前 ...

  4. 微信小程序开发中常见问题及解决方法

    本文章总结小程序开发中常见的错误问题.希望能帮助初学者少走弯路,避免类似的错误. 1:出现"脚本错误或者未正确调用Page()"的错误提示. 解决方法:出现这个错误的原因通常是因为 ...

  5. 微信小程序用户未授权bug解决方法,微信小程序获取用户信息失败解决方法

    微信小程序开发交流qq群   173683895    承接微信小程序开发.扫码加微信. 正文: bug示例图: 导致这个bug的原因是 wx.getUserInfo(OBJECT) 接口做了调整: ...

  6. 微信小程序包体积过大解决方法

    因为微信开发者工具提交需要整个项目大小不超过2M,超过2M则不能提交,会出现下面这个报错 解决方法: 1.在Hbuilder x上面勾选上运行时压缩代码 2.分包操作 在pages.json文件中设置 ...

  7. 微信小程序canvas画布不清晰解决方法

    绘制的图片,文字等十分模糊 添加以下代码,通过设置分辨率来解决 const dpr = wx.getSystemInfoSync().pixelRatiocanvas.width = res[0].w ...

  8. 微信小程序bindtap不生效的解决方法

    用bindtap监听输入框的时候不生效可以尝试将基础库调成最新的版本,如下: 详情 -> 调试基础库

  9. 微信小程序 请求函数 同步封装方法

    微信小程序 请求函数 同步封装方法 距上回说到,我们使用微信小程序请求函数时,需要多次调用,之前我们封装了一套代码,但是他是异步的,当我们下一个请求函数需要的数据是上一个请求函数得到的时候,就不可以了 ...

最新文章

  1. mysql binlog恢复sql_binlog2sql实现MySQL误操作的恢复
  2. matlab stract结构_MATLAB 的基础知识
  3. Docker技术入门与实战 第二版-学习笔记-9-Docker Compose 项目-2-Compose 命令说明
  4. QT的QSortFilterProxyModel类的使用
  5. AdventureWorksDW 2019还原图解
  6. c++中有表示正无穷的数吗_简单的数
  7. Java并发编程的基础-interrupt方法
  8. Django05: 请求生命周期流程图/路由层
  9. 信息抽取--新词提取
  10. Android代码优化,主界面卡住
  11. 漫画 | 强化学习这都学不会的话,咳咳,你过来下!
  12. HTTP-Runoob:教程
  13. js 正则去前后空格且长度不大于20_js去除空格的正则用法
  14. Windows 80端口被System进程占用的解决
  15. 真核有参转录组测序标准分析
  16. centos7安装noIP-动态域名解析最佳实践
  17. 方维带货直播最新教程原创文档-申请腾讯云密钥
  18. AI笔记: 数学基础之反函数和6个基本初等函数
  19. C# ip地址的查询
  20. 看板 工具_2019年14种最佳看板工具

热门文章

  1. lire Demo download
  2. 骨干网络对比-EfficientNet-Lite
  3. 【POJ】POJ题目分类
  4. capped collection
  5. 整理linux 查看操作系统、CPU、内存、磁盘等信息
  6. 禁止输入特殊符号和空格
  7. 【大数据开发运维解决方案】hadoop fs常用命令案例解释
  8. 【iScroll源码学习01】准备阶段 - 叶小钗
  9. 如何在洛谷个人主页显示视频
  10. C语言 --- void的用法解析