@vuemap/amap-jsapi-loader
Version:
高德官网提供的地图JSAPI加载器,可以避免多种异步加载API的错误用法
372 lines (361 loc) • 12.6 kB
text/typescript
enum LoadStatus {
notload = "notload",
loading = "loading",
loaded = "loaded",
failed = "failed",
}
let config = {
key: "",
AMap: {
version: "1.4.15",
plugins: [],
},
AMapUI: {
version: "1.1",
plugins: [],
},
Loca: {
version: "1.3.2",
},
} as any;
let Status = {
AMap: LoadStatus.notload,
AMapUI: LoadStatus.notload,
Loca: LoadStatus.notload,
};
let Callback: {
AMap: any[],
AMapUI: any[],
Loca: any[]
} = {
AMap: [],
AMapUI: [],
Loca: [],
};
let onloadCBKs: any[] = [];
const onload = function (callback) {
if (typeof callback == "function") {
if (Status.AMap === LoadStatus.loaded) {
callback(window.AMap);
return;
}
onloadCBKs.push(callback);
}
};
interface LoadOption {
key: string;
version?: string;
plugins?: string[];
AMapUI?: {
version?: string;
plugins?: string[];
};
Loca?: {
version?: string;
};
}
function appendOther(option: LoadOption): Promise<any> {
let pros: Promise<void>[] = [];
if (option.AMapUI) {
pros.push(loadAMapUI(option.AMapUI));
}
if (option.Loca) {
pros.push(loadLoca(option.Loca));
}
return Promise.all(pros);
}
function loadAMapUI(params: { version?: string; plugins?: string[] }): Promise<void> {
return new Promise((res, rej) => {
const newPlugins: string[] = [];
if (params.plugins) {
for (let i = 0; i < params.plugins.length; i += 1) {
if (config.AMapUI.plugins.indexOf(params.plugins[i]) == -1) {
newPlugins.push(params.plugins[i]);
}
}
}
if (Status.AMapUI === LoadStatus.failed) {
rej("前次请求 AMapUI 失败");
} else if (Status.AMapUI === LoadStatus.notload) {
Status.AMapUI = LoadStatus.loading;
config.AMapUI.version = params.version || config.AMapUI.version;
const version = config.AMapUI.version;
const parentNode = document.body || document.head;
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `https://webapi.amap.com/ui/${version}/main.js`;
script.onerror = (e) => {
Status.AMapUI = LoadStatus.failed;
rej("请求 AMapUI 失败");
};
script.onload = () => {
Status.AMapUI = LoadStatus.loaded;
if (newPlugins.length) {
window.AMapUI.loadUI(newPlugins, function () {
for (let i = 0, len = newPlugins.length; i < len; i++) {
const path = newPlugins[i];
const name = path.split("/").slice(-1)[0];
window.AMapUI[name] = arguments[i];
}
res();
while (Callback.AMapUI.length) {
Callback.AMapUI.splice(0, 1)[0]();
}
});
} else {
res();
while (Callback.AMapUI.length) {
Callback.AMapUI.splice(0, 1)[0]();
}
}
};
parentNode.appendChild(script);
} else if (Status.AMapUI === LoadStatus.loaded) {
if (params.version && params.version !== config.AMapUI.version) {
rej("不允许多个版本 AMapUI 混用");
} else {
if (newPlugins.length) {
window.AMapUI.loadUI(newPlugins, function () {
for (let i = 0, len = newPlugins.length; i < len; i++) {
const path = newPlugins[i];
const name = path.split("/").slice(-1)[0];
window.AMapUI[name] = arguments[i];
}
res();
});
} else {
res();
}
}
} else {
if (params.version && params.version !== config.AMapUI.version) {
rej("不允许多个版本 AMapUI 混用");
} else {
Callback.AMapUI.push((err) => {
if (err) {
rej(err);
} else {
if (newPlugins.length) {
window.AMapUI.loadUI(newPlugins, function () {
for (let i = 0, len = newPlugins.length; i < len; i++) {
const path = newPlugins[i];
const name = path.split("/").slice(-1)[0];
window.AMapUI[name] = arguments[i];
}
res();
});
} else {
res();
}
}
});
}
}
});
}
function loadLoca(params: { version?: string }): Promise<void> {
return new Promise((res, rej) => {
if (Status.Loca === LoadStatus.failed) {
rej("前次请求 Loca 失败");
} else if (Status.Loca === LoadStatus.notload) {
Status.Loca = LoadStatus.loading;
config.Loca.version = params.version || config.Loca.version;
const version = config.Loca.version;
const isApiV2 = config.AMap.version.startsWith("2");
const isLocaV2 = version.startsWith("2");
if ((isApiV2 && !isLocaV2) || (!isApiV2 && isLocaV2)) {
rej("JSAPI 与 Loca 版本不对应!!");
return;
}
const key = config.key;
const parentNode = document.body || document.head;
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `https://webapi.amap.com/loca?v=${version}&key=${key}`;
script.onerror = (e) => {
Status.Loca = LoadStatus.failed;
rej("请求 AMapUI 失败");
};
script.onload = () => {
Status.Loca = LoadStatus.loaded;
res();
while (Callback.Loca.length) {
Callback.Loca.splice(0, 1)[0]();
}
};
parentNode.appendChild(script);
} else if (Status.Loca === LoadStatus.loaded) {
if (params.version && params.version !== config.Loca.version) {
rej("不允许多个版本 Loca 混用");
} else {
res();
}
} else {
if (params.version && params.version !== config.Loca.version) {
rej("不允许多个版本 Loca 混用");
} else {
Callback.Loca.push((err) => {
if (err) {
rej(err);
} else {
rej();
}
});
}
}
});
}
const load = function (options: LoadOption) {
if (typeof window === 'undefined') {
throw Error("AMap JSAPI can only be used in Browser.");
}
return new Promise((resolve, reject) => {
if (Status.AMap == LoadStatus.failed) {
reject("");
} else if (Status.AMap == LoadStatus.notload) {
//初次加载
let { key, version, plugins } = options;
if (!key) {
reject("请填写key");
return;
}
if (window.AMap && location.host !== "lbs.amap.com") {
reject("禁止多种API加载方式混用");
}
config.key = key;
config.AMap.version = version || config.AMap.version;
config.AMap.plugins = plugins || config.AMap.plugins;
Status.AMap = LoadStatus.loading;
const parentNode = document.body || document.head;
window.___onAPILoaded = function (err) {
delete window.___onAPILoaded;
if (err) {
Status.AMap = LoadStatus.failed;
reject(err);
} else {
Status.AMap = LoadStatus.loaded;
appendOther(options)
.then(() => {
resolve(window.AMap);
})
.catch(reject);
while (onloadCBKs.length) {
onloadCBKs.splice(0, 1)[0]();
}
}
};
const script = document.createElement("script");
script.type = "text/javascript";
script.src =
"https://webapi.amap.com/maps?callback=___onAPILoaded&v=" +
config.AMap.version +
"&key=" +
key +
"&plugin=" +
config.AMap.plugins.join(",");
script.onerror = (e) => {
Status.AMap = LoadStatus.failed;
reject(e);
};
parentNode.appendChild(script);
} else if (Status.AMap == LoadStatus.loaded) {
//deal multi load
if (options.key && options.key !== config.key) {
reject("多个不一致的 key");
return;
}
if (options.version && options.version !== config.AMap.version) {
reject("不允许多个版本 JSAPI 混用");
return;
}
const newPlugins: any[] = [];
if (options.plugins) {
for (var i = 0; i < options.plugins.length; i += 1) {
if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
newPlugins.push(options.plugins[i]);
}
}
}
if (newPlugins.length) {
window.AMap.plugin(newPlugins, () => {
appendOther(options)
.then(() => {
resolve(window.AMap);
})
.catch(reject);
});
} else {
appendOther(options)
.then(() => {
resolve(window.AMap);
})
.catch(reject);
}
} else {
// loading
if (options.key && options.key !== config.key) {
reject("多个不一致的 key");
return;
}
if (options.version && options.version !== config.AMap.version) {
reject("不允许多个版本 JSAPI 混用");
return;
}
const newPlugins: any[] = [];
if (options.plugins) {
for (var i = 0; i < options.plugins.length; i += 1) {
if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
newPlugins.push(options.plugins[i]);
}
}
}
onload(() => {
if (newPlugins.length) {
window.AMap.plugin(newPlugins, () => {
appendOther(options)
.then(() => {
resolve(window.AMap);
})
.catch(reject);
});
} else {
appendOther(options)
.then(() => {
resolve(window.AMap);
})
.catch(reject);
}
});
}
});
};
function reset() {
delete window.AMap;
delete window.AMapUI;
delete window.Loca;
config = {
key: "",
AMap: {
version: "1.4.15",
plugins: [],
},
AMapUI: {
version: "1.1",
plugins: [],
},
Loca: {
version: "1.3.2",
},
};
Status = {
AMap: LoadStatus.notload,
AMapUI: LoadStatus.notload,
Loca: LoadStatus.notload,
};
Callback = {
AMap: [],
AMapUI: [],
Loca: [],
};
}
export default { load, reset };