145 lines
3.2 KiB
TypeScript
145 lines
3.2 KiB
TypeScript
/**
|
|
* JSONP 工具函数
|
|
* 用于跨域请求
|
|
*/
|
|
|
|
interface JsonpOptions {
|
|
timeout?: number
|
|
callbackName?: string
|
|
callbackParam?: string
|
|
}
|
|
|
|
/**
|
|
* JSONP 请求
|
|
* @param url 请求地址
|
|
* @param options 配置选项
|
|
* @returns Promise
|
|
*/
|
|
export function jsonp(url: string, options: JsonpOptions = {}): Promise<any> {
|
|
const {
|
|
timeout = 10000,
|
|
callbackName = `jsonp_callback_${Date.now()}_${Math.random().toString(36).substr(2)}`,
|
|
callbackParam = "callback",
|
|
} = options
|
|
|
|
return new Promise((resolve, reject) => {
|
|
// 创建 script 标签
|
|
const script = document.createElement("script")
|
|
|
|
// 设置超时
|
|
const timer = setTimeout(() => {
|
|
cleanup()
|
|
reject(new Error("JSONP request timeout"))
|
|
}, timeout)
|
|
|
|
// 清理函数
|
|
const cleanup = () => {
|
|
if (script.parentNode) {
|
|
script.parentNode.removeChild(script)
|
|
}
|
|
if ((window as any)[callbackName]) {
|
|
delete (window as any)[callbackName]
|
|
}
|
|
clearTimeout(timer)
|
|
}
|
|
|
|
// 设置全局回调函数
|
|
;(window as any)[callbackName] = (data: any) => {
|
|
cleanup()
|
|
resolve(data)
|
|
}
|
|
|
|
// 处理错误
|
|
script.onerror = () => {
|
|
cleanup()
|
|
reject(new Error("JSONP request failed"))
|
|
}
|
|
|
|
// 构建请求 URL
|
|
const separator = url.includes("?") ? "&" : "?"
|
|
const requestUrl = `${url}${separator}${callbackParam}=${callbackName}`
|
|
|
|
// 发起请求
|
|
script.src = requestUrl
|
|
document.head.appendChild(script)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 腾讯地图 API JSONP 请求封装
|
|
*/
|
|
export class TencentMapAPI {
|
|
private apiKey: string
|
|
|
|
constructor(apiKey: string) {
|
|
this.apiKey = apiKey
|
|
}
|
|
|
|
/**
|
|
* 逆地址解析
|
|
* @param lat 纬度
|
|
* @param lng 经度
|
|
* @returns Promise
|
|
*/
|
|
async reverseGeocode(lat: number, lng: number): Promise<any> {
|
|
const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=${this.apiKey}&get_poi=1&output=jsonp`
|
|
|
|
try {
|
|
const data = await jsonp(url)
|
|
return data
|
|
} catch (error) {
|
|
console.error("逆地址解析失败:", error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 地址搜索
|
|
* @param keyword 搜索关键词
|
|
* @param boundary 搜索范围
|
|
* @returns Promise
|
|
*/
|
|
async searchLocation(keyword: string, boundary: string = "region(全国,0)"): Promise<any> {
|
|
const url = `https://apis.map.qq.com/ws/place/v1/search?boundary=${encodeURIComponent(boundary)}&keyword=${encodeURIComponent(
|
|
keyword,
|
|
)}&page_size=10&page_index=1&key=${this.apiKey}&output=jsonp`
|
|
|
|
try {
|
|
const data = await jsonp(url)
|
|
return data
|
|
} catch (error) {
|
|
console.error("地址搜索失败:", error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 地址解析(正向地理编码)
|
|
* @param address 地址
|
|
* @returns Promise
|
|
*/
|
|
async geocode(address: string): Promise<any> {
|
|
const url = `https://apis.map.qq.com/ws/geocoder/v1/?address=${encodeURIComponent(address)}&key=${this.apiKey}&output=jsonp`
|
|
|
|
try {
|
|
const data = await jsonp(url)
|
|
return data
|
|
} catch (error) {
|
|
console.error("地址解析失败:", error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POI 搜索
|
|
* @param keyword 搜索关键词
|
|
* @param boundary 搜索范围
|
|
* @returns Promise
|
|
*/
|
|
async searchPOI(keyword: string, boundary: string = "region(全国,0)"): Promise<any> {
|
|
return this.searchLocation(keyword, boundary)
|
|
}
|
|
}
|
|
|
|
export default jsonp
|