function RemoGeoLocation () { this._remoteSvrUrl = 'https://webapi.amap.com/html/geolocate.html' this._callbackList = [] this._seqBase = 1 this._frameReady = 0 this._watchIdMap = {} } RemoGeoLocation.prototype = { _getSeq: function () { return this._seqBase++ }, _onRrameReady: function (callback) { if (this._frameReady === 0) { if (!this._frameReadyList) { this._frameReadyList = [] } this._frameReadyList.push(callback) this._prepareIframe() return } callback.call(this) }, _prepareIframe: function () { if (this._iframeWin) { return } var ifrm = document.createElement('iframe') ifrm.src = this._remoteSvrUrl + (this._remoteSvrUrl.indexOf('?') > 0 ? '&' : '?') ifrm.width = '0px' ifrm.height = '0px' ifrm.style.position = 'absolute' ifrm.style.display = 'none' var self = this var timeoutId = setTimeout(function () { self._frameReady = false self._callbackFrameReadyList() }, 5000) ifrm.onload = function () { clearTimeout(timeoutId) self._frameReady = true self._callbackFrameReadyList() ifrm.onload = null } document.body.appendChild(ifrm) this._iframeWin = ifrm.contentWindow window.addEventListener( 'message', function (e) { if (self._remoteSvrUrl.indexOf(e.origin) !== 0) { return } self._handleRemoteMsg(e.data) }, false ) }, _callbackFrameReadyList: function () { if (this._frameReadyList) { var list = this._frameReadyList this._frameReadyList = null for (var i = 0, len = list.length; i < len; i++) { list[i].call(this, this._frameReady) } } }, _pickCallback: function (seqNum, keepInList) { var callbackList = this._callbackList for (var i = 0, len = callbackList.length; i < len; i++) { var cbkInfo = callbackList[i] if (seqNum === cbkInfo.seq) { if (!keepInList) { callbackList.splice(i, 1) } return cbkInfo } } }, _handleRemoteMsg: function (msg) { var seqNum = msg.seq var cbkInfo = this._pickCallback(seqNum, !!msg.notify) if (cbkInfo) { cbkInfo.cbk.call(null, msg.error, msg.result) } else { console.warn('Receive remote msg: ', msg) } }, _postMessage: function (cmd, args, callback, seq) { this._prepareIframe() var msg = { cmd: cmd, args: args, seq: seq || this._getSeq() } this._callbackList.push({ cbk: callback, seq: msg.seq }) this._onRrameReady(function () { if (this._frameReady === true) { try { this._iframeWin.postMessage(msg, '*') } catch (e) { this._pickCallback(msg.seq) callback(e) } } else { this._pickCallback(msg.seq) callback({ message: 'iFrame load failed!' }) } }) }, getCurrentPosition: function (succHandler, errHandler, options) { this._postMessage('getCurrentPosition', [options], function (err, result) { if (err) { if (errHandler) { errHandler(err) } return } if (succHandler) { succHandler(result) } }) }, watchPosition: function (succHandler, errHandler, options) { var watchKey = 'wk' + this._getSeq() var cmdSeq = this._getSeq() this._watchIdMap[watchKey] = { stat: 0, seq: cmdSeq } var self = this this._postMessage( 'watchPosition', [options], function (err, result) { var id = null if (result) { id = result.id } var watchInfo = self._watchIdMap[watchKey] watchInfo.id = id watchInfo.stat = 1 if (watchInfo.callbackList) { var list = watchInfo.callbackList watchInfo.callbackList = null for (var i = 0, len = list.length; i < len; i++) { list[i].call(self, id) } } if (err) { if (errHandler) { errHandler(err) } return } if (succHandler) { succHandler(result.pos) } }, cmdSeq ) return watchKey }, clearWatch: function (watchKey, callback) { if (!this._watchIdMap[watchKey]) { callback('Id not exists: ' + watchKey) return } var watchInfo = this._watchIdMap[watchKey] var self = this function clearId (id) { self._postMessage('clearWatch', [id], function (err, result) { if (!err) { self._pickCallback(watchInfo.seq) delete self._watchIdMap[watchKey] } if (callback) { callback(err, result) } }) } if (watchInfo.stat < 1) { if (!watchInfo.callbackList) { watchInfo.callbackList = [] } watchInfo.callbackList.push(function (id) { clearId(id) }) } else { clearId(watchInfo.id) } } } export default RemoGeoLocation