【问题标题】:Leaflet wait for promise to resolve传单等待承诺解决
【发布时间】:2021-01-30 19:20:59
【问题描述】:

我正在扩展 Leaflet getTileUrl 以获得某种缓存图块。我使用 Vue,但它不应该影响任何东西。目前看起来是这样的:

   //step 1 
   L.TileLayer.MyLayer = L.TileLayer.extend({
        getTileUrl: function(coords) {
            
            var url = this.getLayerUrl(coords.z, coords.x, coords.y);

            return url;

        }.bind(this)
    });

    //step 2
    L.tileLayer.myLayer =  function() {
        return new L.TileLayer.MyLayer();
    }

    //step 3
    L.tileLayer.myLayer().addTo(this.getParent('main-map').map);

问题在于 getLayerUrl 函数返回一个承诺。即使我尝试为 this.getLayerUrl 制作 getTileUrl async 而不是 await (并且还制作异步等待步骤 2 和 3)或放置 .then(function(result) {return result;} this.getLayerUrl 之后,Leaflet 在浏览器控制台中显示错误,它试图从 url 获取图块:GET http://localhost/project/public/ [object%20Promise]

另外我应该提到 this.getLayerUrl 为每个图块返回不同的 url,它实际上是一个 blob url,如:blob:http://localhost/f7c4298f-9e9d-423f-9d0b-3f7a301e433f 但如果正确返回了 url传单没有问题,并且正确显示了瓷砖。

【问题讨论】:

  • 看起来传单需要同步计算磁贴 url。为什么会是异步的?只有从该 url 加载图像应该是异步的。
  • 听起来更像是 Leaflet Grid Layer 的用例

标签: javascript caching promise leaflet


【解决方案1】:

这里的方法不是提供getLayerUrl 方法,而是替换 createTile 元素的实现。

original createTile implementation 替换createTile 实现的"noop" 替换看起来像:

L.TileLayer.MyLayer = L.TileLayer.extend({
  getTileUrl: function (coords) {
    var tile = document.createElement("img");

    DomEvent.on(tile, "load", Util.bind(this._tileOnLoad, this, done, tile));
    DomEvent.on(tile, "error", Util.bind(this._tileOnError, this, done, tile));

    if (this.options.crossOrigin || this.options.crossOrigin === "") {
      tile.crossOrigin =
        this.options.crossOrigin === true ? "" : this.options.crossOrigin;
    }

    tile.alt = "";
    tile.setAttribute("role", "presentation");

    tile.src = this.getTileUrl(coords);

    return tile;
  }
});

考虑到该实现,可以以异步方式设置 HTMLImageElementsrc 属性,将同步的 tile.src = this.getTileUrl(coords); 替换为类似以下内容:

asyncGetLayerUrl(coords)
  .then(function (url) {
    tile.src = url;
  })

并且,为了更好地衡量,通过调用 this._tileOnError 来处理承诺拒绝,例如:

asyncGetLayerUrl(coords)
  .then(function (url) {
    tile.src = url;
  })
  .catch(
    function (err) {
      this._tileOnError(done, tile, err);
    }.bind(this)
  );

【讨论】:

    【解决方案2】:

    不幸的是,您想要实现的目标是不可能的。 getTileUrl() 方法应该直接返回 url,即不包含在 promise 中。但是,您会从 getLayerUrl 获得返回承诺的 url。您根本无法在getTileUrl() 中同步等待promise 的结果。

    await 关键字表明这是可能的,但事实并非如此。 await 只是语法糖,是链接承诺的简写。我举个简单的例子。

    function getUrl() {
        return getAsyncUrl().then(url => {
             return transformUrl(url);
        });
    }
    

    async/await 允许你这样写:

    async function getUrl() {
        const url = await getAsyncUrl();
        return transformUrl(url);
    }
    

    但在幕后它仍然使用承诺。 async 函数总是返回一个承诺。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-25
      • 2019-04-29
      • 2018-04-02
      • 1970-01-01
      • 2014-03-12
      • 2021-11-26
      • 2014-10-29
      • 1970-01-01
      相关资源
      最近更新 更多