You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS:如何在WebMidi.enable回调函数中调用类方法

解决WebMidi回调中引用类方法的问题

这个问题我之前也碰到过,核心就是回调函数里的this指向问题,以及要确保fillDropdown在WebMidi真正启用后再执行。咱们一步步来解决:

核心问题分析

你现在的代码里有两个关键问题:

  1. fillDropdown在constructor里直接调用了,但WebMidi.enable是异步操作,这时候WebMidi还没完成启用,WebMidi.inputs自然是空的。
  2. 普通的function作为回调时,内部的this不会指向类实例,而是指向全局对象(浏览器中为window),所以即使你在回调里写this.fillDropdown也会报错或者找不到方法。

解决方案1:使用箭头函数(推荐)

箭头函数不会创建自己的this,它会继承外层作用域的this(也就是类实例的this)。修改你的enable方法如下:

class MidiListener{
  constructor(){
    this.enable();
    // 移除这里的fillDropdown调用,等待WebMidi启用后再执行
  }
  enable(){
    WebMidi.enable((err) => { // 替换成箭头函数
      if (err) {
        console.log("WebMidi could not be enabled.", err);
        window.alert("WebMidi is not supported by your Browser.")
      } else {
        console.log("WebMidi enabled!");
        this.fillDropdown(WebMidi.inputs); // 现在this能正确指向类实例
      }
    });
  }
  fillDropdown(inputs) {
    // 你的下拉菜单填充逻辑
    // 比如遍历inputs,添加option到下拉框
    inputs.forEach(input => {
      console.log("检测到MIDI输入设备:", input.name);
      // 这里写添加到下拉菜单的代码
    });
  }
}

解决方案2:保存this到变量

如果你不想用箭头函数,可以在enable方法里先把类实例的this保存到一个变量(比如self),然后在回调里用这个变量访问类方法:

class MidiListener{
  constructor(){
    this.enable();
  }
  enable(){
    const self = this; // 保存类实例的this
    WebMidi.enable(function (err) {
      if (err) {
        console.log("WebMidi could not be enabled.", err);
        window.alert("WebMidi is not supported by your Browser.")
      } else {
        console.log("WebMidi enabled!");
        self.fillDropdown(WebMidi.inputs); // 使用self代替this
      }
    });
  }
  fillDropdown(inputs) {
    // 你的填充逻辑
  }
}

解决方案3:用bind绑定this

你也可以通过bind方法,把回调函数的this强制绑定到类实例:

class MidiListener{
  constructor(){
    this.enable();
  }
  enable(){
    WebMidi.enable(function (err) {
      if (err) {
        console.log("WebMidi could not be enabled.", err);
        window.alert("WebMidi is not supported by your Browser.")
      } else {
        console.log("WebMidi enabled!");
        this.fillDropdown(WebMidi.inputs);
      }
    }.bind(this)); // 绑定this到类实例
  }
  fillDropdown(inputs) {
    // 你的填充逻辑
  }
}

额外提醒

除了调整this的指向,一定要确保fillDropdown是在WebMidi启用成功的回调里调用,而不是在constructor里直接调用——因为WebMidi.enable是异步的,只有当回调触发时,WebMidi才真正准备好,WebMidi.inputs才会包含真实的设备列表。

内容的提问来源于stack exchange,提问作者Nils

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:59:09