2.22 支持的浏览器及代码差异化

支持的浏览器

JS API基于两种软件运行体系来进行封装,一种是使用ActiveX控件版本的SDK原生API进行封装;另一种是采用了跨浏览器通信插件的API进行封装。这样可以使JS API从根本上支持更多的浏览器。

目前的支持情况如下表:

IE8 IE11 Google Chrome Microsoft Edge(旧版) Microsoft Edge(新版) FireFox
不支持 支持 支持 不支持 支持(尚存问题) 暂不支持

不同浏览器间的通信机制

首先造成代码差异化的原因是:IE下的SDK的通信机制是同步的,即方法调用,获得结果,结果继续传递给下个方法,列举如下:

// IE下的常规调用模式
// 调用get()获取变量a的值
var a = get();
// 将变量a的值作为参数传给set()方法,并获得变量b的值
var b = set(a);
// 将变量a与变量b的值相加的结果作为参数传给cal()方法,并获得结果变量c的值
var c = cal(a + b);

在非IE浏览器下,SDK的通信机制是异步的,即方法调用,等待结果,获得结果后,继续传递给下个方法,列举如下:

// 非IE下的常规调用模式
// 调用get()获取变量a的值
get(function(a){
    // 将变量a的值作为参数传给set()方法,并获得变量b的值
    set(a, function(b){
        // 将变量a与变量b的值相加的结果作为参数传给cal()方法,并获得结果变量c的值
        cal(a + b, function(c){
            //输出c...
            console.log(c);
        });
    });
});

可以发现,异步通信下的写法非常繁琐,同时让人不好理解。

JS API为了让开发者在不同浏览器上运行CooSDK时,对代码的改动量达到最小,因此在内部做了大量的针对性处理,尽可能少的使用异步处理,但不可避免的是,这种异步机制是贯穿代码运行始终的,开发者仍需知道有这么一种机制,才能在使用JS API时不存在认知性障碍。

API对象剖析

举一个JS API中常用的对象PositionObj的例子,对其进行深度的剖析。

该对象的构造函数实现大致如下:

    function PositionObj(x, y, z) {
        this._x = x;
        this._y = y;
        this._z = z;
        this._map = null;
        this._position = null;
        try {
            if (Element.prototype.CooGisSDKCtrl) {
                this._map = Element.prototype.Map;
            } else {
                this._map = document.getElementById("CooRunSDK").GetIMapMgrPtr();
            }
        } catch (e) {
            console.log("PositionObj failed");
        }
        if (defined(this._map)) {
            this._position = this._map.CreatePosition(this._x, this._y, this._z);
        }
    }

可以发现构造函数里调用了原生API的 CreatePosition 方法,这个方法创建了一个IPositionPtr对象,该对象内含GetX(),GetY(),GetZ()这三个方法。因此PositionObj的x、y、z属性,实质上是分别调用了GetX(),GetY(),GetZ()这三个方法来获得的。

我们用JS API写个简单的例子:

var posA = new CooSDK.PositionObj(120, 30, 0);
var posB = new CooSDK.PositionObj(posA.x, posA.y, posA.z + 10);

将其实际的API流程代入后,是这样子的:

var posA = new CooSDK.PositionObj(120, 30, 0);
var posB = new CooSDK.PositionObj(posA.position.GetX(), posA.position.GetY(), posA.position.GetZ() + 10);

在IE浏览器下,这是同步的通信调用方式,这种写法不存在任何问题。

但在非IE浏览器下,其处于异步的通信调用方式,拿下面的写法来举例:

var posB = new CooSDK.PositionObj(posA.position.GetX(), posA.position.GetY(), posA.position.GetZ() + 10);

在非IE浏览器中,此时posA.position.GetX()的返回值并不是x,而是JS API临时生成的一个具有唯一id标识的对象,以此类推,可以发现

posA.position.GetZ() + 10

这句话会产生明显的问题,object对象+数字是错误的语法。所以得换成异步的写法:

posA.position.GetZ(function(z){
    var posB = new CooSDK.PositionObj(posA.position.GetX(), posA.position.GetY(), parseFloat(z) + 10);
});

我们再假设一种情况,即posA.position.GetZ()不加减值了,写法如下:

var posB = new CooSDK.PositionObj(posA.position.GetX(), posA.position.GetY(), posA.position.GetZ());

这种写法在非IE浏览器下也是支持的,但细心的人会发现,PositionObj构造函数需要的是数值类型的参数,才能成功创建对象,在这里传入的都是对象,为何能这么写也是可以的?其实在这里,SDK跨浏览器插件内部做了相应的处理,根据传入的对象唯一id找到SDK对应存储区域的值,进行了后台处理,因此开发者也是可以这么写的,避免了大量的异步写法。

由此根据上述内容总结,开发者在非IE浏览器下开发时,需要注意通信机制本质上的变化,JS API已经尽可能的封装了实现细节,降低代码变化的感知。这些改变在API文档中会有大量的体现,主要体现在调用接口获得返回值的流程是异步的,需要在回调里进行处理,开发时务必关注这类参数变化。

results matching ""

    No results matching ""