Promise.all 应用一例
在做小程序地图开发的时候,需要在地图上放置不同图标的 markers
,而这些图标又来自网络,恰恰由于微信小程序的限制,不支持网络图片作为 markers
的 iconPath
值
但注意到也支持临时路径这句话,则可以先通过 wx.downloadFile
将图片先下载下来,恰好 wx.downloadFile
返回的是一个临时路径
基本的思路有了,但实践发现,微信小程序的 map
组件,实现有 bug
,markers
不能频繁更新,否则 marker
在 ios
下会莫名消失
因此,应该将全部的网络图片全部下载下来后,再整体设置 markers
,Promise.all
是完成这类任务,最好的工具之一
1、首先对 wx.downloadFile
进行 Promise
改造
代码如下:
// 下载网络文件到本地,即使失败,也要用默认值 defVal resolve
const downloadFile = (url, defVal) => {
return new Promise((resolve, reject) => {
wx.downloadFile({
url,
success(res) {
resolve(res.tempFilePath)
},
fail() {
// 即使失败,也要 resolve
resolve(defVal)
}
})
})
}
这里设计为,即便图片下载失败,也要用一个默认图标 resolve
,上述代码,理论上不会 reject
2、下载所有图标,并制作对应关系 Map
假设 list
是全部的图标列表数组,数组中的每一项的数据结构为:
{
id: 1, // 图标 ID
lng: 166.8888, // 经度
lat: 28.8888, // 维度
img: 'https://.../xxx.jpg', // 图标图片网址
}
列表中的 img
有重复的,所以第一步,我们获取所有 img
并虑重:
const allImgList = list.map(it => it.img).filter(it => !!it)
const imgList = unique(allImgList)
unique
是一个工具函数,用来数组虑重,这里就不展示了
接着,调用 downloadFile
下载所有所有图片,并用 Promise.all
等待所有图片被下载下来:
Promise.all(imgList.map(it => downloadFile(it, '../../images/food.png')))
.then(pathList => {
const imgMap = combine(imgList, pathList)
return imgMap
})
combine
是另外一个工具函数,功效与 php
的 array_combine
相同,它接受两个数组参数,用第一个数组的每一项做 key
,第二个数组的每一项为 value
,组成一个新对象
可以看出,这个新对象就是我们所需要的,img
网络地址,到微信小程序临时路径的映射 Map
这里的要点是,Promise.all 会按照数据源的顺序返回结果
3、一次性设置 markers
代码很简单,主要是按照微信小程序文档加工数据:
// 这一段是重复上面的代码
Promise.all(imgList.map(it => downloadFile(it, '../../images/food.png')))
.then(pathList => {
const imgMap = combine(imgList, pathList)
return imgMap
})
// 以下才是本节演示代码
.then(imgMap => {
// 按照微信小程序文档加工数据
const markers = list.map(({ id, lng, lat, img }) => {
return {
id,
longitude: lng,
latitude: lat,
iconPath: imgMap[img],
width: 36,
height: 36,
}
})
this.setMarkers(markers)
}
this.setMarkers
是具体设置 makers
的代码,无非是调用微信小程序的 setData
,这里就不展示了
如果裸写微信小程序(即不用任何高层框架),它对
Promise
支持并不好,需要引入Promise
外部库,建议大家用美团开源的框架mpvue
4、结语
Promise
是非常伟大的发明,虽然,你也可以用其他代码,实现 Promise
的效果,但既然 Promise
从 n 个优秀异步方案中脱颖而出,成为 javascript
的标准,其魅力自是锐不可当,你又何必非要自己造轮子呢?
这里推荐一篇关于 Promise
的好文章(需要翻墙,下同):https://developers.google.com/web/fundamentals/primers/promises
当然,Promise
并不是最优方案,窃以为,异步函数(async function)才是未来,但它是以 Promise
为基础的,同样一篇好文章推荐给大家:
https://developers.google.com/web/fundamentals/primers/async-functions
整篇完。欢迎转载,转载请注明出处:
简书作者:lip2up
微信公众号:前端大牛