Javascript;在运行剩余代码之前将数据从 url 加载到对象变量中

问题描述 投票:0回答:1

我正在努力理解 javascript 异步/同步概念。

我已经对 openlayers Layer 类进行了子类化,以便在地图中进行一些自定义渲染。实例化类的对象后,我想加载数据(来自 url 的 png 文件)并将数据保存到类变量中,然后再继续根据数据进行一些自定义 webgl 渲染。我现在已经尝试了各种各样的东西,但无法让某些东西发挥作用。我希望有人能给我一些指导,告诉我应该如何构建代码来实现这一目标。

当我在类外部加载数据时,我可以做到这一点,但只能使用固定的 url,并且我需要能够在某些事件上更改 url。

用于实例化对象并尝试运行在类变量中设置数据的函数的代码:

function update_map(time_change_event) {
    const new_url = 'www.example.com/' + time_change_event.detail.key
    const canvasLayer = new CanvasLayer({})
    canvasLayer.getData(new_url)
    map.addLayer(canvasLayer)
    map.removeLayer(*oldlayer*)
}

自定义类代码:

export class CanvasLayer extends Layer {

    data = null;

    getData(url){

        async data_promise = new Promise((resolve, reject) => {
            const image = new Image();
            image.onload = () => {
                const canvas = document.createElement('canvas');
                canvas.width = image.width;
                canvas.height = image.height;
                const context = canvas.getContext('2d');
                context.drawImage(image, 0, 0);
                const data = context.getImageData(0, 0, width, height);
                resolve(data);
            
            };
            image.onerror = () => {
                reject(new Error('failed to load'));
            };

            image.src = url;
        })
    
        this.data = await data_promise;

    }

    render(frameState, target){
        // This is called when layer is added to map
        // Doing stuff with this.data does not work because it is null
        console.log(this.data) returns null
    }
}
javascript class es6-promise openlayers
1个回答
0
投票

为了解释 @David 所说的内容,这里有一些与 Promise 和异步函数有关的事情。这是仅使用简单承诺的一种选择:

export class CanvasLayer extends Layer {
  data = new Promise()

  getData(url) {
    this.data = new Promise((resolve, reject) => {
      const image = new Image()
      image.onload = () => {
        const canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        const context = canvas.getContext('2d')
        context.drawImage(image, 0, 0)
        const data = context.getImageData(0, 0, width, height)
        resolve(data)
      }
      image.onerror = () => {
        reject(new Error('failed to load'))
      }

      image.src = url
    })
  }

  render(frameState, target) {
    this.data.then((imageData) => {
      console.log('Image data:', imageData)
    })
  }
}

它的作用是创建一个新的 Promise 并将其存储在类中以供以后使用。当您调用 render 时,您实际上只是挂钩该 Promise 并告诉它在 Promise 解析时运行一个函数。

您还可以使函数异步并具有如下内容:

async render(frameState, target) {
  let imageData = await this.data
  console.log('Image data:', imageData)
}

说明

Promise 和异步的东西在 js 中可能会变得非常混乱。但这里有一些经验法则:

  1. await
    只能在异步函数中使用(截至 2024 年,尽管这可能会随着一些新的 js 功能(如顶级等待)而改变)
  2. Promises 是一个像其他任何东西一样的对象,它本质上是你在代码中说的方式“这不会立即有值,但我promise它最终会到达”。
  3. 您可以通过等待 Promise 或通过将
    then
    链接到它来从 Promise 中获取值;但无论哪种方式,您都需要告诉代码“只需等待该值到来,在此之前您不需要执行任何其他操作。”

这里有一些关于异步函数的更多信息:异步函数-developer.mozilla.org

以及有关 Promise 的一些信息:Promise -developer.mozilla.org

© www.soinside.com 2019 - 2024. All rights reserved.