赞
踩
长话短说,不扯那些晦涩难懂的定义,只讲promise类怎么使用:
根据我的使用经验,promise类的应用场景为:代码执行过程中让程序停下来等待某个耗时较长的函数执行完毕后再继续往下执行。
需求:写一个签到函数,验证用户当前地理位置是否在签到范围内,若在则记录签到成功。
函数有两个步骤:1.获取地理位置,2.比对地理位置
- signTest() {
- let lat = -1;
- let lon = -1;
- //微信官方提供的获取经纬度的函数
- wx.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- highAccuracyExpireTime: 5000,
- success(res) {
- //获取到经纬度后输出
- lat = res.latitude;
- lon = res.longitude;
- console.log('1获取到经纬度了','lat=',lat,'lon=',lon);
-
- //以下应该验证当前位置是否在签到范围内,在此省略
- },
- fail(err) {
- console.log('获取地理位置失败:',err);
- },
- });
- //程序不会等待wx.getLocation执行完毕,而是直接执行以下语句
- console.log('2经纬度为:','lat=',lat,'lon=',lon);
- },
然后我们来执行这个signTest函数试试:
可以看到代码执行顺序为:
①console.log('2经纬度为:','lat=',lat,'lon=',lon)
②console.log('1获取到经纬度了','lat=',lat,'lon=',lon);
说明在遇到耗时较长的函数时,代码不会等待函数执行完毕,会直接继续执行下去。那么,该怎么解决呢?
办法有三:
1.使用回调函数,即上述wx.getLocation里的success函数,将所有接下来的代码都放在在success函数里
2.使用promise,然后将所有接下来的代码都放在.then()函数中
3.使用await,async关键字配合promise,让代码停下来等待该函数执行完毕再继续往下走
我并不推荐1,2,因为这么写的话,简单点的函数还好,一旦逻辑稍微复杂一些,代码就会一层套一层的,难以解耦,分离,就像函数瀑布,维护起来也很头疼,推荐第三种写法,为什么下面会讲
接下来我会讲解2,3怎么实现
首先,将耗时长的函数这么处理:
- myGetLocation() {
- return new Promise((resolve, reject) => {
- wx.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- highAccuracyExpireTime: 5000,
- success(res) {
- let lat = res.latitude;
- let lon = res.longitude;
- resolve({ lat: lat, lon: lon });
- },
- fail(err) {
- reject(err);
- }
- })
- })
- }
就是用
return new Promise((resolve, reject) => { })将该函数包裹起来,然后将原函数将返回的结果放在resolve()里面,reject()为出错时使用,一般不用。
这下我们这么写就能实现办法2:
- signTest(){
- let lat = -1;
- let lon = -1;
- //微信官方提供的获取经纬度的函数
- this.myGetLocation()
- .then((res:any)=>{
- console.log('wx.getLocation执行结果为:',res);
- });
- //程序不会等待getLocation执行完毕,而是直接执行以下语句
- console.log('2经纬度为:', 'lat=', lat, 'lon=', lon);
- },
- myGetLocation() {
- return new Promise((resolve, reject) => {
- wx.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- highAccuracyExpireTime: 5000,
- success(res) {
- let lat = res.latitude;
- let lon = res.longitude;
- resolve({ lat: lat, lon: lon });
- },
- fail(err) {
- reject(err);
- }
- })
- })
- }
执行结果为:
可以看到,这么写的话,通过myGetLocation()的.then()函数就能拿到myGetLocation内部放在resolve里的值,但是还是同一开始一样,程序依然执行到底,而不会停下来等待,该写法同回调函数差不多,也不推荐
加上await与async关键字就能实现办法3:
- signTest:async function(){
- let lat = -1;
- let lon = -1;
- //微信官方提供的获取经纬度的函数
- await this.myGetLocation()
- .then((res:any)=>{
- console.log('wx.getLocation执行结果为:',res);
- lat=res.lat;
- lon=res.lon;
- });
- //程序会等待getLocation执行完毕,然后执行以下语句
- console.log('2经纬度为:', 'lat=', lat, 'lon=', lon);
- },
在signTest后面加上async声明,然后就可以在signTest内使用await关键字了,await关键字会迫使代码停下,等待await的promise函数执行完毕,再继续执行
执行结果如下:
可以看到,这次真的是停下来等待了。
根据我的编程经验,使用await可以避免函数瀑布的出现,可以直观地看一下:
- test(){
- function1().then((res:any)=>{
- //其他代码
- function2().then((res:any)=>{
- //其他代码
- function3().then((res:any)=>{
- //其他代码
- })
- })
- })
- },
- test2():async function(){
- await function1().then({
- //其他代码
- });
- await function2().then({
- //其他代码
- });
- await function3().then({
- //其他代码
- });
- }
在实践中,是第二种写法更赏心悦目,更容易解耦,分离逻辑。
想要让promise函数有返回值也很简单,在.then()或.catch()中使用return就行。
比如,改进上述3的实现:
- signTest:async function(){
- let lat = -1;
- let lon = -1;
- let res =await this.myGetLocation().then((res:any)=>{return res;});
- lat=res.lat;
- lon=res.lon;
- console.log('经纬度为:', 'lat=', lat, 'lon=', lon);
- },
看看,是不是感觉变的非常赏心悦目,获取经纬度的代码仅仅一行就搞定了!
再比较一下原本的signTest函数:
- signTest() {
- let lat = -1;
- let lon = -1;
- wx.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- highAccuracyExpireTime: 5000,
- success(res) {
- //获取到经纬度后输出
- lat = res.latitude;
- lon = res.longitude;
- console.log('获取到经纬度了','lat=',lat,'lon=',lon);
- },
- fail(err) {
- console.log('获取地理位置失败:',err);
- },
- });
- },
如何?get到区别了吗?
正确地使用promise类可以让前端代码的耦合度飞快下降,更容易理清楚哪一块是干什么的,非常有利于后续维护,改进。非常推荐使用!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。