最近碰到一个需求,就是将咱们系统中要导出一系列的工做数据,这里面有一个需求就是根据工做人员的经纬度去获取他可能的位置。说到这里你们确定能想到用地图API了,我这里用的是百度地图的API(详情可参考)。而后这里就涉及到一个问题,工做数据是不少条的,可是这里的API很明显就只能一条一条的去请求,那么咱们怎么封装可以达到咱们的目的呢。javascript
首先呢,咱们想要使用百度地图相关的API的话,确定是要去注册申请相关的使用资格的,详细的帐号申请流程呢,请戳这里,这里面详细介绍了如何注册并申请百度AK,只有拿到了AK,咱们在使用相关的API时才会有效,不然是不生效的话,因此你们必定要保证有AK而且是有效的哈。php
申请好了AK以后呢,这里有两种使用方法: 一种是直接经过url来进行请求,像是下边这种html
http://api.map.baidu.com/geocoder?location=39.910093,116.403945&output=json&key=你的百度AK
复制代码
这种方法使用的话,你们能够直接把这个url放到axios或者ajax里面,而后他的回调里面返回的就是咱们想要的地址等相关信息了。另外一种方法就是官网里面介绍的方法:java
// 初始化地图,这里的window可能须要从父组件传过来,原理还没弄清楚
var map = new window.BMap.Map("allmap");
// 建立地理编码实例
var myGeo = new window.BMap.Geocoder();
// 根据坐标获得地址描述
myGeo.getLocation(new window.BMap.Point(116.404, 39.915), function(result){
if (result){
console.log('这就是解析以后的地址了',resule.address)
}
})
复制代码
注意:用第二种方法的话,咱们须要在index.html里面引用咱们上面的AK,以下ios
<script src="https://api.map.baidu.com/api?v=2.0&ak=你的百度AK&s=1"></script>
复制代码
上面的两种方法,均可以达到咱们获取地址信息的目的哈。我这里选用的是第二种方法,而后后面咱们批量请求的话,也是针对第二种方式来进行改装的。git
刚开始个人思路是想着,既然这种方法只可以一条一条请求的话,那我就将经纬度构建成一个数组,经过循环调用的方法来给这个数组中的值赋值,代码以下ajax
gpsDatas.forEach((gpsItem)=>{
var map = new window.BMap.Map("allmap");
// 建立地理编码实例
var myGeo = new window.BMap.Geocoder();
// 根据坐标获得地址描述,将每一项的经纬度传入
myGeo.getLocation(new window.BMap.Point(gpsItem.longitude, gpsItem.latitude), function(result:any){
if (result){
// 将返回的值赋给该字段
gpsItem.maybePosition = result.address
}
})
})
// 返回咱们要输出的数据
console.log('gpsDatas',gpsDatas)
console.log('gpsDatas[0]',gpsDatas[0].maybePosition)
let a = gpsDatas[0].maybePosition
return gpsDatas
复制代码
若是你们执行到了这里的话,咱们就会发现一个很经典的问题,也是咱们常常可能会碰到的问题,就是咱们能够看到第一个打印出来的gpsDatas数组里面是可以看到咱们拿到了咱们想要的值,可是第二个打印咱们可能就会看到一个undefined了,那么有小伙伴就可能会产生这样一个疑惑了,为何我明明打印出来看有这个值,可是为何取不到值呢,这是由于在咱们取值的时候,myGeo.getLocation这个异步函数尚未执行完毕,因此取值的时候咱们是取不到这个值的,可是由于gpsDatas是一个引用数据类型,因此在异步函数执行完毕后,他会把数据填充到这个数组里面,由于引用地址没有改变,因此咱们能够看到数组中的地址已经有值了。json
能够这样理解,console输出数据的时候,他输出引用数据类型和基本数据类型是不一样的。输出引用类型的话,其实他是输出了一个指针,咱们看到的就是指向内存中的一片地址中的数据,因此尽管他是后边异步把数据放上来的,可是由于空间指向没有改变,因此输出的数据其实一直是在改变的,不过是console没有把这一步表现出来而已。axios
那么很显然,如今这种状况确定是不知足咱们的需求的,那么这里咱们就须要将咱们的方法就行改装一下了。api
通过前面的分析,咱们可知,问题的产生是由于咱们是一个循环调用异步函数的问题,循环先走完了,可是异步没有走完,因此致使咱们取不出数据,那么你们其实很容易想到Promise,咱们能够利用Promise.all,将全部的异步操做一块儿执行,而后在.then里面获取返回结果。实现以下:
getMaybePositionByLaLo(window,positionDatas){
// 定义一个Promise数组,来将异步操做放进来
let apiDatas = []
positionDatas.forEach((gpsItem)=>{
let apiItem = this.getMapInfo(window,gpsItem)
apiDatas.push(apiItem)
})
// 这里.all会将全部的异步操做一块儿放在队列中,等待全部异步执行完毕后才会执行.then,这就保证了咱们的同步获取数据
return Promise.all(apiDatas)
.then((gpsData)=>{
return gpsData
})
}
// 将单个获取地理位置的方法封装成一个方法
// 这里传入window的目的是,有些地方直接new BMap会报错,须要new window.BMap才能够
getMapInfo(window,gpsItem){
return new Promise((resolve, reject)=>{
var map = new window.BMap.Map("allmap");
// 建立地理编码实例
var myGeo = new window.BMap.Geocoder();
// 根据坐标获得地址描述
myGeo.getLocation(new window.BMap.Point(gpsItem.longitude, gpsItem.latitude), function(result){
if (result){
gpsItem.maybePosition = result.address;
resolve(gpsItem)
}
})
})
}
// 而后咱们就能够在页面直接调用了
this.getMaybePositionByLaLo(window,positionDatas)
.then((positionDatas)=>{
// 这里就能够去进行咱们的取值赋值操做了
})
复制代码
以上咱们就完成了咱们的批量改装,其实核心就是对于Promise的应用,如何合理的运用Promise,对于咱们之后的开发有着很大的好处,我也是最近才开始发现Promise的好处,以前只是了解,也没有多的去使用,欢迎你们之后一块儿学习指正。