微信小程序异步回调函数恶梦和解决办法

问题

先看看下面的代码,是读写取腾讯cos,因为几个对象间是有层次关系的,要读出一个取值然后作为另一个的条件,再去读,依次有几层关系。 按照官方文档,每一次都要放在回调函数里取结果,这样一层一层嵌套起来,可读性非常的差。 而且还有个致命的问题,这些回调函数都是异步处理的,当同一层并依序并列处理时,因为异步原因,没法按代码顺序来执行。

     cos.getBucket({
            Bucket: Bucket,
            Region: Region,
            Prefix:  preday, // 这里传入列出的文件前缀
          },
          function (err, data) {
            if (data) {
              console.log(data)
              var count = 0
              var len = data.Contents.length
              console.log('len', len)
              for (var i = 0; i < len; i++) {
                var key2 = data.Contents[i].Key;

                cos.getObject({
                  Bucket: Bucket,
                  Region: Region,
                  Key: key2,
                }, function (err, data) {
                  count++;
                  console.log(data)
                  if (data) {
                    var obj = JSON.parse(data.Body);
                    recent = that.data.recent;
                    var uname = obj.uname
                    cos.getObject({
                      Bucket: Bucket,
                      Region: Region,
                      Key:  uname,
                    }, function (err, data) {
                      var obj = JSON.parse(data.Body);
                      recent.push({
                        uid: obj.uid,
                        date_expire: obj.date_expire
                      });
                    })
                    if (count >= len) {
                      let s1 = new Set(recent); 
                      recent = Array.from(s1);
                      console.log('array',recent)
                      that.setData({
                        recent: recent
                      });
                      console.log('recent', that.data.recent,that.data.list)
                    }
                  }
                });
              };
            };
          }
        ); 


        if (that.data.inputValue != '') {
          cos.getObject({
            Bucket: Bucket,
            Region: Region,
            Key:  that.data.inputValue,
          }, function (err, data) {
            //console.log(err || data.Body);
            if (data) {
              var obj = JSON.parse(data.Body);
              var uname = obj.uname;
              var ary = uname.split('+');
              var remark = "";
              if (obj.remark) {
                remark = obj.remark
              };
              that.setData({
                corpid: ary[0],
                agentid: ary[1],
                uid: that.data.inputValue,
                userid: ary[2],
                remark: remark
              });

              cos.getObject({
                Bucket: Bucket,
                Region: Region,
                Key: uname,
              }, function (err, data) {
                if (data) {
                  var obj = JSON.parse(data.Body);
                  var date_expire = obj.date_expire;

                  that.setData({
                    date_expire: date_expire
                  });
                }

              });

              cos.getBucket({
                  Bucket: Bucket,
                  Region: Region,
                  Prefix: that.data.corpid, 
                },
                function (err, data) {

                  //console.log(err || data.Contents);
                  if (data) {
                    var list = []
                    var count = 0
                    var len = data.Contents.length
                    for (var i = 0; i < len; i++) {
                      var key2 = data.Contents[i].Key;

                      cos.getObject({
                        Bucket: Bucket,
                        Region: Region,
                        Key: key2,
                      }, function (err, data) {
                        count++;
                        if (data) {
                          var obj = JSON.parse(data.Body);
                          list = that.data.list;
                          var arr2 = key2.split('+')
                          list.push({
                            uid: obj.uid,
                            date_expire: obj.date_expire
                          });
                          console.log(count, len)
                          if (count >= len) {
                            let s1 = new Set(list);
                            list = Array.from(s1);
                            that.setData({
                              list: list
                            })
                          }
                        }
                      });
                    };
                  };
                }
              );
            }
          });
        }; 

解决方法

可以使用 Promise 来重新包装一下 COS 的接口如下:这样这些函数就变成同步的方式来调用了。

//get bucket contents from prefix
const getBucket = (Prefix) => {
  return new Promise((resolve, reject) => {
    cos.getBucket({
      Bucket: Bucket,
      Region: Region,
      Prefix: Prefix,
    }, function (err, data) {
      if (err) {
        //console.log('error', err)
        reject(err)
      } else {
        //console.log('success', data)
        resolve(data.Contents)
      }
    });
  });
} //end getBucket

//get object from key
const getObject = (Key) => {
  return new Promise((resolve, reject) => {
    cos.getObject({
      Bucket: Bucket,
      Region: Region,
      Key: Key,
    }, function (err, data) {
      if (err) {
        //console.log('error2', err)
        reject(err)
      } else {
        //console.log('success2', data)
        resolve(data.Body)
      }
    });
  });
} //end getObject  

//put object to key
const putObject = (Key, Body) => {
  return new Promise((resolve, reject) => {
    cos.putObject({
      Bucket: Bucket,
      Region: Region,
      Key: Key,
      Body: Body
    }, function (err, data) {
      if (err) {
        reject(err)
      } else {
        //console.log(data)
        resolve(data)
      }
    });
  });
} //end putObject 

调用的方式,有几点要求,首先调用的主函数定义前必须加上 async ,其次在调用上面包装好的函数时,要加 await.  如下:

  async Test(e){
    let rlt1 = await getObject('keyname')
    rlt1 = JSON.parse(rlt1)
  },

扩展

另外 微信小程序的库里本身带的很多函数就是支持这种调用的方式,以支持同步执行的方式如所示:

    // wx.showModal 官方文档中的调用方式,这种是异步的方式
    // 执行会发现 最后面的 log('3')会先输出,log('2')反而后输出。
    console.log('1')
    wx.showModal({
      title: '提示',
      content: '这是一个模态弹窗',
      success(res) {
        if (res.confirm) {
          console.log('用户点击确定')
          console.log('2')
        } else if (res.cancel) {
          console.log('用户点击取消')
          console.log('2')
        }
      }
    });
    console.log('3')

    //可以改成下面的调用方式,就能顺序执行了。
    let res = await wx.showModal({
      title: '提示',
      content: '这是一个模态弹窗'
    });
    if (res.confirm) {
      console.log('用户点击确定')
      console.log('2')
    } else if (res.cancel) {
      console.log('用户点击取消')
      console.log('2')
    }
    console.log('3')

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wxgnolux

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值