fetch后在函数中使用layer

Use layer in function after fetch

第一次使用服务器和fetch功能,不是很了解。有人可以帮忙吗? 基本上我已经获取了一个我想添加到我的地图的空间层,但这必须通过按下按钮来完成。当我在没有服务器的情况下工作时,它工作得很好,但现在不行了。因此我的问题是:如何从获取技术中获取变量?

这是我的代码:

fetch('loisirs_all_repro', { credentials: 'include' })
    .then(response => response.json())
    .then(data => {
        console.log(data);
        process1(data);
    })
;
function process1(donnees){
  var bati_loisirs = L.geoJson(donnees,{
    style:styleall,
  });
  function styleall(features) {
    return {
        weight:12,
        opacity: 0.1,
        color: getColor(features.properties.Intensite),
        dashArray: '1',
        fillOpacity: 1
    };
  };
}

/*Display/hide the spatial layer when button is clicked*/

$("#button3").click(function(event) {
    event.preventDefault();
    if(map.hasLayer(bati_loisirs)) {
        $(this).removeClass('selected');
        map.removeLayer(bati_loisirs);
    } else {
        map.addLayer(bati_loisirs);        
        $(this).addClass('selected');
   }
}); 

This extensive answer 从异步调用中获取数据可能会有所帮助,但眼前的问题是您的 bati_loisirs 变量仅存在于 process1 函数的范围内。一旦该函数退出 bati_loisirs 不再存在。

因此,当您在按钮单击处理程序中执行 map.hasLayer(bati_loisirs) 时,您将收到错误消息。这是问题的最小演示。这不起作用:

function a() {
  let bati_loisirs = 'foo'; // only exists within function a
}

function b() {
  console.log(bati_loisirs); // Uncaught ReferenceError: bati_loisirs is not defined
}

a();
b();

一种补救措施是将 bati_loisirs 变量声明移出到全局范围,以便它随处可用:

let bati_loisirs;

function a() {
  bati_loisirs = 'foo'; // reassigning variable from outer scope
}

console.log(bati_loisirs); // 'undefined', hasn't been set yet.
a();
console.log(bati_loisirs); // 'foo', value changed by a() call

这种方法的主要问题是它会用您的变量污染全局范围,并且有可能发生变量名冲突。 (如果其他一些脚本也声明了一个 bati_loisirs 变量,就会出现问题。)

更好的解决方案是将所有内容移动到同一范围内,这在您的特定情况下非常简单:

fetch('loisirs_all_repro', {
    credentials: 'include'
  })
  .then(response => response.json())
  .then(data => {
    console.log(data);
    // get the layer
    const bati_loisirs = process1(data);

    // add the click handler
    $("#button3").click(function(event) {
      event.preventDefault();
      if (map.hasLayer(bati_loisirs)) {
        $(this).removeClass('selected');
        map.removeLayer(bati_loisirs);
      } else {
        map.addLayer(bati_loisirs);
        $(this).addClass('selected');
      }
    });
  });

function process1(donnees) {
  // return the layer so the caller can use it
  return L.geoJson(donnees, {
    style: features => ({
      weight: 12,
      opacity: 0.1,
      color: getColor(features.properties.Intensite),
      dashArray: '1',
      fillOpacity: 1
    }),
  });
}

这假定您不需要在其他任何地方引用 bati_loisirs

最后,如果您不想在获取中完成所有操作,您可以 await the response:

async function setUp() {
  const data = await fetch('loisirs_all_repro', {
    credentials: 'include'
  })
  .then(response => response.json())

  const bati_loisirs = process1(data);

  // add the click handler
  $("#button3").click(function(event) {
    event.preventDefault();
    if (map.hasLayer(bati_loisirs)) {
      $(this).removeClass('selected');
      map.removeLayer(bati_loisirs);
    } else {
      map.addLayer(bati_loisirs);
      $(this).addClass('selected');
    }
  });
}

function process1(donnees) {
  // return the layer so the caller can use it
  return L.geoJson(donnees, {
    style: features => ({
      weight: 12,
      opacity: 0.1,
      color: getColor(features.properties.Intensite),
      dashArray: '1',
      fillOpacity: 1
    }),
  });
}

setUp();

编辑:使用模块

除了最简单的玩具应用程序之外的任何东西都会很快变得难以管理和维护,这就是为什么 javascript 添加了对 modules 的支持,允许您将应用程序分解成逻辑块,其中每个块(模块)可以专注于特定的事情。

我建议您阅读优秀的 MDN guide on modules,但这里是您如何将其应用到当前任务的简要说明。

基本思想是将所有层管理放在一个模块中,并且仅将有用的部分暴露在模块本身之外。

所以您可能有一个 getLayer 函数,您的应用程序可以使用该函数来获取特定层。所有的获取和解析逻辑都被抽象出来,隐藏在 getLayer 实现中:

import { getLayer } from 'layers.js';

const bati_loisirs = getLayer('loisirs_all_repro');

// do stuff with bati_loisirs

您可以通过创建两个模块来设置它:1) 导出“getLayers”的“层”模块,以及 2) 使用层模块的“app”模块。 (请注意,名称“layers”和“app”是任意的。您可以随意调用它们。)

在实践中,您的 layers.js 模块可能看起来像这样:

// layers.js

// A mapping of paths to layers. Not exported, so only visible within this module
const layers = {};

 // exported. this is the only part of the module visible from the outside.
export async function getLayer(path) {
    if (!layers[path]) {
        // if we don't already have it do the fetch and add it to the mapping
        layers[path] = await fetchLayer(path);
    }
    // return the layer for the given path from the mapping
    return layers[path];
}

// "private" functions for fetching and processing data

async function fetchLayer(path) {
    return fetch('loisirs_all_repro', { credentials: 'include' })
        .then(response => response.json())
        .then(data => process1(data))
}

function process1(donnees){
  return L.geoJson(donnees,{
    style: () => ({
        weight:12,
        opacity: 0.1,
        color: getColor(features.properties.Intensite),
        dashArray: '1',
        fillOpacity: 1
    }),
  });
}

然后你的 app.js 模块可以导入 getLayers 并使用它,如上例所示:

// app.js

import { getLayer } from './layers';

async function app () {
  const bati_loisirs = getLayer('loisirs_all_repro');
  // do stuff with bati_loisirs
}

app();

您可以在浏览器中使用它,方法是在您的 html 页面中包含主模块并指定 type="module":

<script type="module" src="./app.js"></script>

我知道要吸收的内容很多。希望对您有所帮助。