Javascript: 在异步通信中继续循环之前等待 MIDI 设备的响应

Javascript: waiting for response from a MIDI device before continuing loop in asynchronous communication

我正在使用带有 Web MIDI 的 MIDI 协议 API 与 MIDI 设备通信。 每次等待响应或超时发送下一条消息时,我都想向此设备发送 MIDI 消息。通过

收到回复

我想要以下内容:

//gotMIDImessage will be called when the message is received
midiIn.onmidimessage = gotMIDImessage;
function gotMIDImessage(messageData) {
  //Do something with the data
}
//send bunch of messages in a loop and wait for responce each time
function askDevice(){
  for (var i=0;i<n;i++){
    for (var j=0;j<m;j++){
      midiOut.send([0xF0,0x52,0x00,0x61,0x09,0x00,i,j,0xF7]);
      //wait for gotMIDImessage or timeout to continue and do something about the response hre
    }
  }
}

这是我的第一次尝试:

midiIn.onmidimessage = gotMIDImessage;

function gotMIDImessage(messageData) {
  received.innerHTML=received.innerHTML+"<br>"+messageData.data;
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(1);
    }, 100);
  });
}


async function askDevice() {
  var o = {'data': 'await'};
  for (var i=0;i<5;i++){
    for (var j=0;j<3;j++){
      var res=await gotMIDImessage(o);
      midiOut.send([0xF0,0x52,0x00,0x61,0x09,0x00,i,j,0xF7]);
    }
  }
}

显然是行不通的,因为await gotMIDImessage();调用了函数gotMIDImessage(),但是这个函数在收到消息时会自动触发。

我怎样才能做到这一点?

编辑:我也试过这个版本,但似乎不起作用

received=null;
midiMessage=null;
function gotMIDImessage(messageData) {
  received=true;
  midiMessage=messageData.data;
}

function sendWait(message){
  received=false;
  midiOut.send(message);
  function waitForIt(){
    if(!received){
      setTimeout(function(){waitForIt()},1000);
    }else{
      alert("received");
    }
  } 
  return midiMessage;
}
function askDevice() {
  var o = {'data': 'await'};
  for (var i=0;i<5;i++){
    for (var j=0;j<3;j++){
      res=sendWait([0xF0,0x52,0x00,0x61,0x09,0x00,i,j,0xF7]);
    }
  }
}

res 始终为空,循环结束后我收到了所有 15 条消息

你可以这样做:

function awaitReply(msg, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const gotMidiMessage = msg => {
      midiIn.removeEventListener('midimessage', gotMidiMessage); // Removing the event listener again
      resolve(msg);
    };
    midiIn.addEventListener('midimessage', gotMidiMessage);
    midiOut.send(msg);
    setTimeout(() => {
      // Don't forget to remove the event listener
      midiIn.removeEventListener('midimessage', gotMidiMessage);
      /* Resolve the Promise anyway ... */
      resolve(null);
      /* ... OR reject it, but then you have to catch the error in the call */
      // reject('Error message');
    }, timeout);
  });
}

async function askDevice() {
  for (let i = 0; i < 5 ; i++) {
    for (let j = 0; j < 3; j++) {
      let res = await awaitReply([0xF0, 0x52, 0x00, 0x61, 0x09, 0x00, i, j, 0xF7]);
    }
  }
}

这是一个工作示例:

function awaitReply(msg) {
  return new Promise(resolve => {
    const gotMidiMessage = messageData => {
      window.removeEventListener('midimessage', gotMidiMessage); // Removing the event listener again
      resolve(messageData);
    };
    window.addEventListener('midimessage', gotMidiMessage);
    midiOut.send(msg);
  });
}

async function askDevice() {
  for (let i = 0; i < 5 ; i++) {
    for (let j = 0; j < 3; j++) {
      let res = await awaitReply([0xF0, 0x52, 0x00, 0x61, 0x09, 0x00, i, j, 0xF7]);
      // Logging your iterator variable which you want to send
      console.log(res.detail[6], res.detail[7]);
    }
  }
}

const midiOut = {
  send(msg) {
    return setTimeout(() => {
      let evt = new CustomEvent('midimessage', { detail: msg });
      window.dispatchEvent(evt);
    }, 1000);
  }
};

askDevice();