微信小程序中关于异步接口

写在前面

今天也是写微信小程序的一天,真真切切的体会到了什么叫做异步。之前写其他代码,从来没考虑过什么异步,同步的,也基本不用不到。而在微信小程序中不得不考虑了。毕竟 文档 中指明了:

小程序是基于双线程模型,那就意味着任何数据传递都是线程间的通信,也就是都会有一定的延时。这不像传统Web那样,当界面需要更新时,通过调用更新接口 UI 就会同步地渲染出来。在小程序架构里,这一切都会变成异步。

除了逻辑层与渲染层之间的通信有延时,各层与客户端原生交互同样是有延时的。以逻辑层为例,开发者的代码是跑在逻辑层这个线程之上,而客户端原生是跑在微信主线程(安卓上是线程)之上,所以注册给逻辑层有关客户端能力的接口,实际上也是跟微信主线程之间的通信,同样意味着有延时。这也是我们看到大部分提供的接口都是异步的原因。

小插入

使用了一个 map 原生组件差点心态爆炸。页面加载后,视觉中心竟然不是自己当前位置,而是大老远的北京。最后发现所谓视觉中心原来是指 map 中的属性 longitudelatitude

官方示例

<map id="map" longitude="113.324520" latitude="23.099994" scale="14" controls="{{controls}}" bindcontroltap="controltap" markers="{{markers}}" bindmarkertap="markertap" polyline="{{polyline}}" bindregionchange="regionchange" show-location style="width: 100%; height: 300px;"></map>

更多属性说明查阅 文档

我的代码

<map id="map" scale="14" controls="{{controls}}" bindcontroltap="controltap" markers="{{markers}}" bindmarkertap="markertap" bindregionchange="regionchange" show-location style="width: 100%; height: 950rpx;" bindtap="getloc"></map>

自己没有设置 longitudelatitude 的属性值,结果它给我默认为 longitude="113.324520" latitude="23.099994"。也就是北京的经纬度。我寻思着文档中也没说默认值是多少,而且还是必填属性,怎么我没有设置,也不给我报错呢(/哭笑)。它既然可以标注我的位置,为什么不干脆把视觉中心设置成当前位置(/哭笑)。惹不起,还是要自己调 wx.getLocation 接口获取当前位置。像这样:

wxml

<map id="map" scale="16" longitude="{{longitude}}" latitude="{{latitude}}" controls="{{controls}}" bindcontroltap="controltap" markers="{{markers}}" bindmarkertap="markertap" bindregionchange="regionchange" show-location style="width: 100%; height: 950rpx;" bindtap="getloc"></map>

JS 代码片段

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (option) {
    var that = this
    console.log('---onLoad---')
    // 获取用户位置
    wx.getLocation({
      type: 'gcj02',
      success:res=> {
        console.log('---getLocation success---')
        const latitude = res.latitude
        const longitude = res.longitude
        const speed = res.speed
        const accuracy = res.accuracy
        that.setData({
            latitude: latitude,
            longitude: longitude
        })
      },
      fail:res=> {
        console.log('---getLocation fail---')
      },
      complete:res=> {
        console.log('---getLocation complete---')
      }
    })
	console.log('---onLoad over---')
  },

异步

百度词条

异步双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位。

异步的另外一种含义是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。

前面也提到了,微信小程序中大部分提供的接口是异步的。这也就是为什么许多接口中都提供了这样的方法:success fail 以及 complete。显而易见,上面的 wx.getLocation 也是异步接口。为了便于更直观的调试,上面的 JS 代码中添加了几个 console.log 语句。运行后可以在控制台看见这样的输出信息(一部分):

	...省略···
	---onLoad---
	---onLoad over---
	...省略···
	---onReady---
	---getLocation success---
	---getLocation complete---
	...省略···

这样的输出很直观的体会到异步的概念。console.log('---onLoad over---')wx.getLocation 后面却先执行完毕了。甚至在小程序页面周期进入 onReady 了,wx.getLocation 才执行完毕。

wx.getLocation

获取当前的地理位置、速度。当用户离开小程序后,此接口无法调用。开启高精度定位,接口耗时会增加,可指定 highAccuracyExpireTime 作为超时时间

这是因为当遇到一个比较耗时的 异步 API 时,并不会阻塞当前线程,wx.getLocation 本身会在在另一个线程里执行,所以就先执行后面的程序了。而提供 success fail 以及 complete 这样的方法恰恰就是方便我们对其进行监控。

注意

对异步接口有了一些了解后,在调用接口时就不得考虑一些逻辑先后问题了。例如这样修改上面的那段代码:

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (option) {
    var that = this
    console.log('---onLoad---')
    // 获取用户位置
    wx.getLocation({
      type: 'gcj02',
      success:res=> {
        console.log('---getLocation success---')
        const latitude = res.latitude
        const longitude = res.longitude
        const speed = res.speed
        const accuracy = res.accuracy
        that.setData({
            latitude: latitude,
            longitude: longitude
        })
      },
      fail:res=> {
        console.log('---getLocation fail---')
        console.log(res)
      },
      complete:res=> {
        console.log('---getLocation complete---')
      }
    })
	// 改变视觉中心
	if(option.lat != null){
		that.setData({
			latitude: option.lat,
            longitude: option.lng,
        })
	}
	consolo.log(that.data.latitude)
  },

假设这里 data 中的 longitudelatitude 初始值都是 null。当有一个类似这样的页面跳转时:

wx.navigateTo({
	url: '../index/index?lat='+lat+'&lng='+lng,
})

我们期待跳转成功后,页面的视觉中心变成位置 lat lng 处。但是运行上面的代码会发现,地图中心的位置依旧在当前位置。控制台输出的 latitude 也正是当前位置的。明显的,传入进来的 lat 和 lng ,被 wx.getLocation 返回的值覆盖了。所以当有类似这样的需求时,我们不得不把后面的代码放在 complete 方法里,以确保这段代码在 wx.getLocation 之后执行。像这样:

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (option) {
    var that = this
    console.log('---onLoad---')
    // 获取用户位置
    wx.getLocation({
      type: 'gcj02',
      success:res=> {
        console.log('---getLocation success---')
        const latitude = res.latitude
        const longitude = res.longitude
        const speed = res.speed
        const accuracy = res.accuracy
        that.setData({
            latitude: latitude,
            longitude: longitude
        })
      },
      fail:res=> {
        console.log('---getLocation fail---')
      },
      complete:res=> {
	    // 改变视觉中心
		if(option.lat != null){
			that.setData({
				latitude: option.lat,
				longitude: option.lng,
			})
		}
        console.log('---getLocation complete---')
      }
    })
	consolo.log(that.data.latitude)
  },

I know nothing but my ignorance.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值