arcgis api 4.11 多线程worker使用

1.项目背景:

     由于软件需要在刚开始启动的时候,只需要加载在一个市区面polygon内的点Graphics数组(相当于相交)到GraphicsLayer中并展现在地图中,这其中就需要过滤掉不在这个polygon内的点,因为我用的GraphicsLayer图层。这个图层并没有提供SpatialFilter之类的方法,能够直接过滤。所以只能选择循环一个个的graphics和polygon进行空间相交运算。 因为Javascript是单线程的,所以导致界面会出现明显的卡顿(卡顿1到2s),这肯定是没办法忍受的。所以开始查找多线程资料,希望能在多线程中完成点的加载

   思路1:使用web worker 将 过滤的这个操作,放在多线程中处理,然后将处理后的数据以数组的形式,传回到主线程中,然后再加载到图层中。  经过测试后,发现这种方式,没办法将arcgis api 的对象(例如graphic、geometry)传入到多线程js文件中。传过去这些对象都不是arcgis api 的对象,相应的属性和方法都没有了。然后我就想说,那我可以在传入之前,先将arc api 对象转换成json对象呢?  经过测试,还是不行。

  思路2:继续查找资料。找到了 arcgis api 原来自带worker类 。。。。  兜兜绕绕一圈子,你去藏在api!

require(["esri/core/workers"], function(workers) { /* code goes here */ });

    那么api对这个worker的解释是:                 

This module is a utility framework that simplifies the use of Web Workers in the ArcGIS API for JavaScript

    //个人翻译:这是一个能在arcgis api中能简化使用 web workers 的框架; 其实就是arcgis api 已经封装好了

web worker,就等我们来用了!  

2.使用教程:

    具体的使用方法,这个api 上已经有了详细的解释。我理解的如下:

     step1:首先配置好 你的需要多线程处理的js文件的路径,其中这个esriConfig 是api 的一个模块。也需要引入!其中的wokerDir属性 就是配置着你的多线程js文件夹路径(这里文件夹的名称是我设置的是workerScripts),里面放着的就是多线程要运行的js文件。

// Set worker's loaderConfig to set up
// a path to folder called workersScripts
esriConfig.workers.loaderConfig = {
 paths: {
   workerDir: window.location.href.replace(/\/[^/]+$/, "/workerScripts"),
 }
};

  step2:运行完配置之后,开始加载这个多线程文件,在这里这个filterPointsByPolygon就是我自己写的多线程中要运行的js文件,其中有一个方法叫做getFilterData,这个方法里面就可以写我自己的业务逻辑。

// Load workerScripts/Calculator.js in the workers framework
// and invoke its "max" method

var filterPolygonJSON=self.filterPolygon.toJSON();
workers.open("workerScripts/filterPointsByPolygon")
  .then(function(connection) {
    return connection.invoke("getFilterData", {
      data:self.data,
      polygon:filterPolygonJSON
    });
  })
  .then(function(result) {
    console.log(result);
  });

     我们重点看一下这个传参.。首先这个self.filterPolygon,这个就是我之前说过的市这个面polygon,这是arcapi中的对象,但是我如果直接把这个filterpolygon传入到多线程文件中,那么也会出现思路一中提到的问题------对象中的属性和方法都没法使用,浏览器不识别

      所以在这里我们做了一个toJSON()的转换。这个转换是Polygon自带的方法,这个转换是很重要的。另外传入的参数里面有一个self.data。这个对象呢(里面包含经纬度。我需要在多线程js文件中把这些经纬度组成一个个的点。然后做相交判断),就是一个js数组对象,js数组对象是可以直接当做参数传参的,所以不用做其他操作,。那么此时,我们已经把需要传入的参数,已经传到了多线程js文件中了。然后再多线程js文件执行完毕后,  会再次回到主线程中的异步方法中,也就是上面的这个then方法,其中的result参数,就是我们多线程js文件传回来 的 已经过滤好的 js数组。

step3:在多线程文件中,我们还是按照 dojo ADM模块写法。来定义个这个多线程js文件,

define(["esri/core/promiseUtils",
        'workerDir/common/js/GeometyHelper',
        'esri/geometry/Point',
        'esri/geometry',
        'esri/geometry/polygon',
        'esri/layers/FeatureLayer',
        'esri/layers/support/Field',
        'esri/Graphic',
        'workerDir/Config/serverUrl'
        ], 
        function(promiseUtils,GeometryHelper,Point,Geometry,Polygon,
        			FeatureLayer,Field,Graphic,serverUrl) {


     var filterPointsByPolygon= function filterPointsByPolygon(){};

     filterPointsByPolygon.prototype.max = function(data) {
         var resultData=[];、
         //接受主线程传过来的参数
         var sourceData=data.data;
         //重新将filterPOlygonJSON转换成arcapi 中的Polygon对象
         var filterPolygon=Polygon.formJSON(data.filterPOlygonJSON);

          
            过滤数据代码

         

      //返回过滤后的数组
      return resultData;

    }
    //返回 filterPointsByPolygon实例
    return filterPointsByPolygon;
})

      这里面还需要注意的是,如果我们需要在多线程js文件中 加载我们自定义的js模块的话,应该怎么办?比如上面代码中我们要加载这个   /common/js/GeometyHelper'   文件。那么还记得我们最开始的时候定义的wokerspripts文件路径吗。这个路径最开始是直接指向了多线程js文件夹。那么我们可以把这个路径往上层路径设置,这样的话,这个路径加上我们拼接的路径。就可以访问到我们的程序中放置在common/js文件夹下的GeometryHelper文件了。其他文件访问类似。

step4:  等到子线程中把过滤后的数据返回到主线程中的then方法中。那么我们就可以将所有点组成graphics添加到graphicsLayer中,然后add到Map中了,至此就完成了多线程过滤点的操作。

 

最后的效果,就是界面不会卡顿。并且点加载的速度也有明显的提升!

/over

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值