ArcGIS4Js重要概念3:编程模式2

接着上篇的ArcGIS4Js重要概念3:编程模式1,进行捋一捋异步(Async Data)和使用 fromJSON (Using fromJSON)。

Async Data(异步)

在ArcGIS API for JavaScript中常用的异步模式有两种:PromisesLoading

Promises

Promises 是API中非常重要的一个概念,使用它可以很简洁的写出异步操作代码,同时多个Promises的顺序执行,是支持链式代码。 每个Promises执行状态都是pending(正在进行)resolved(正常完成)rejected(报错)三种状态中的一个。Promises执行完成可以通过then(callback, errorCallback)方法监听,其中callback为执行成功的回调,
errorCallback为失败回调,是可选参数。

someAsyncFunction()
  .then(function(resolveValue) { //成功回调
    console.log(resolvedValue);
  }, function(error) { //失败回调
    console.log(error);
  });

执行错误的回调,我们还可以使用catch()方法进行捕捉,这个在链式代码中非常有用,可以统计处理异常。

someAsyncFunction()
  .then(function(resolveValue) {//成功回调
    console.log(resolvedValue);
  }, function(error) {//捕捉
    console.log(error);
  });

下面我们来看个使用GeometryService类中的project()方法,将已知点进行投影转换的例子:

require([
  "esri/tasks/GeometryService",
  "esri/tasks/support/ProjectParameters",
  ], function(GeometryService, ProjectParameters) {

    var geoService = new GeometryService( "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer" );

    var projectParams = new ProjectParameters({
      geometries: [points],  //需要转换的点集合
      outSR: outSR,//转换至的坐标系
      transformation = transformation //转换模型
    });

    geoService.project(projectParams)
      .then(function(projectedGeoms){
       console.log("投影转换之后的点: ", projectedGeoms);
      }, function(error){
        console.error(error);
      });
});

Promises还支持链式代码,可以通过多个then(callback)方法进行连接,上一个回调返回值,可以作为下一个回调的参数。例如下面的例子的执行顺序,对输入点投影转换 -> 对转换好点进行缓冲区分析 -> 将缓冲区分析结果面添加到图层中 -> 计算各个缓存面的面积 -> 计算所有缓存面面积和

  var bufferLayer = new GraphicsLayer();


//缓冲区分析
  function bufferPoints(points) {
    return geometryEngine.geodesicBuffer(points, 1000, "feet");
  }


//缓冲面添加到图层
  function addGraphicsToBufferLayer(buffers) {
    buffers.forEach(function(buffer) {
      bufferLayer.add(new Graphic(buffer));
    });
    return buffers;
  }

//计算单个缓冲面面积
  function calculateArea(buffer) {
    return geometryEngine.geodesicArea(buffer, "square-feet");
  }

//分别计算缓冲面面积
  function calculateAreas(buffers) {
    return buffers.map(calculateArea);
  }

//计算面积和
  function sumArea(areas) {
    for (var i = 0, total = 0; i < areas.length; i++) {
      total += areas[i];
    }
    return total;
  }

  geoService.project(projectParams)
    .then(bufferPoints)
    .then(addGraphicsToBufferLayer)
    .then(calculateAreas)
    .then(sumArea)
    .catch(function(error) { //统一处理异常
      console.error("出错啦! Message:", error);
    });

Loadable

API中的layermapportal item等资源加载都是要异步远程服务或本地数据,Loadable模式就是为了方便的监听它们的加载状态,而这些资源都称作可加载资源

可加载资源都有如下只读属性:

  • loaded -> Boolean :资源是否加载完成
  • loadError -> Error :资源加载失败的错误对象
  • loadStatus -> String :资源加载状态,只可能为:not-loaded(还没开始加载)、loading(加载中)、loaded(加载成功)、failed(加载失败)

可加载资源都有如下方法:

  • cancelLoad():取消加载,只有当资源处于loading状态是才有效
  • load() —> Promises :触发加载,并返回Promises,可用于监听加载状态

可加载资源 加载流程图如下:
Load流程

Loadable模式可以自动处理级联依赖(Cascading load dependencies),如下代码,加载webmap就会触发portalItem加载,继而触发portal加载。

var view = new MapView({
  container: "viewDiv"
});

var portal = new Portal({
  url: "https://myportal/"
});

var webmap = new WebMap({
  portalItem: {
    portal: portal,
    id: "f2e9b762544945f390ca4ac3671cfa72"
  }
});

webmap.load()
  .then(function() { view.map = webmap; })
  .catch(function(error) {
    console.error("加载出错啦:", error);
  });

使用 fromJSON

API中的很多类,如Camera,Viewpoint, Color都提供了fromJSON()静态方法。该方法可将ArcGIS各个平台(ArcGIS Server等) ArcGIS REST API或生成的JSON对象转为ArcGIS API for Javascript中的对象。
如下代码将ArcGIS REST API查询返回的SimpleMarkerSymbol Json对象转为ArcGIS API for Javascript中的SimpleMarkerSymbol对象:

require(["esri/symbols/SimpleMarkerSymbol"], function(SimpleMarkerSymbol){
  // 由ArcGIS API for Javascript 产生的Json对象
  var smsJson = {
    "type": "esriSMS",
    "style": "esriSMSSquare",
    "color": [ 76,115,0,255 ],
    "size": 8,
    "angle": 0,
    "xoffset": 0,
    "yoffset": 0,
    "outline":
    {
      "color": [ 152,230,0,255 ],
      "width": 1
    }
  };
  var sms = SimpleMarkerSymbol.fromJSON(smsJson);
});

注意: fromJSON()接收的Json对象看上去和构造函数接收Json对象非常像,但他们两是不一样的东西,千万不要混了。fromJSON()接收的Json对象是ArcGIS平台中通用的格式,而构造函数中接收的Json对象只能在JS API中使用,他们有很多不同的地方。所以如果是ArcGIS平台返回的JSON对象,必须通过fromJSON()进行转换。

使用jsonUtils

除了使用fromJSON()可将Json对象转为API对象,API中还提供多个jsonUtils可将Json对象转为API对象,例如:

  • esri/geometry/support/jsonUtils
  • esri/renderers/support/jsonUtils
  • esri/symbols/support/jsonUtils

通过jsonUtils转换出来的对象是不确定,而通过fromJSON()转换出来是确定的对象。例如我们知道一个ArcGIS REST API返回的是一个Renderer对象,但我们不知道它返回是UniqueValueRenderer或其他Rednerer,这时候我们就可以通过jsonUtils进行转换。

require([ "esri/renderers/support/jsonUtils",
          "esri/layers/FeatureLayer"
], function( rendererJsonUtils, FeatureLayer ){

  var rendererJSON = {// 由REST API生成
     "authoringInfo":null,
     "type":"uniqueValue",
     "field1":"CLASS",
     "field2":null,
     "field3":null,
     "expression":null,
     "fieldDelimiter":null,
     "defaultSymbol":{
        "color":[
           235,
           235,
           235,
           255
        ],
        "type":"esriSLS",
        "width":3,
        "style":"esriSLSShortDot"
     },
     "defaultLabel":"Other major roads",
     "uniqueValueInfos":[
        {
           "value":"I",
           "symbol":{
              "color":[
                 255,
                 170,
                 0,
                 255
              ],
              "type":"esriSLS",
              "width":10,
              "style":"esriSLSSolid"
           },
           "label":"Interstate"
        },
        {
           "value":"U",
           "symbol":{
              "color":[
                 223,
                 115,
                 255,
                 255
              ],
              "type":"esriSLS",
              "width":7,
              "style":"esriSLSSolid"
           },
           "label":"US Highway"
        }
     ]
  };

  // 将JSON对象转为API对象
  var flRenderer = rendererJsonUtils.fromJSON(rendererJSON);

  // 将renderer设置给图层
  var layer = new FeatureLayer({
    renderer: flRenderer
  });
});

最后,重要概念中的编程模式,到这就结束啦,合理利用这些模式,代码将会更加简洁,可读性更高。

欢迎关注我的微信公众号,第一时间为您推送相关教程。

GIS猫公众号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值