承诺等待阻塞循环完成

时间:2021-03-03 02:44:49

标签: javascript async-await promise

我需要一个循环来依次播放 10 个声音。我第一次尝试时声音重叠,所以我被告知我需要使用 Promise/await。下面的代码播放声音 0 然后不再继续循环。

(我使用的库 (jscw) 用于莫尔斯电码。你传递给它一个字符串,它播放莫尔斯等效。它的“onFinished”调用一个用户定义的函数。)

async function playAll() {
  for (let i = 0; i < 10; i++) {
    playMorse(words[i]);
    await playstate();
  }
}

function playstate() {
  playdone = true;
  //console.log(playdone);
  return new Promise((resolve) => {
    window.addEventListener('playdone', resolve)
  })
}

function playMorse(z) {
  var m = new jscw();
  playdone = false;
  m.onFinished = function() {
    playstate();
  }
  m.play(z);
}

1 个答案:

答案 0 :(得分:0)

似乎不应该触发您正在侦听的 playdone 事件。
因此,一个简单的解决方案是在 onFinished 回调中触发它。

const words = ["hello", "world"];
async function playAll() {
  for (let i = 0; i < 2; i++) {
    console.log("###READING", words[i]);
    playMorse(words[i]);
    await playstate();
  }
}

function playstate() {
  playdone = true;
  //console.log(playdone);
  return new Promise((resolve) => {
    window.addEventListener('playdone', resolve, { once: true })
  })
}

function playMorse(z) {
  var m = new jscw();
  playdone = false;
  m.onFinished = function() {
    dispatchEvent( new Event("playdone") );
  }
  m.play(z);
}

btn.onclick = playAll;
<script src="https://fkurz.net/ham/jscwlib/src/jscwlib.js"></script>
<button id="btn">play all</button>

但是这里不需要事件,只需让 playMorse 返回一个将在 onFinished 回调中解析的 Promise:

const words = ["hello", "world"];
async function playAll() {
  for (let i = 0; i < 2; i++) {
    console.log("###READING", words[i]);
    await playMorse(words[i]);
  }
}

function playMorse(z) {
  return new Promise( (resolve) => {
    const m = new jscw();
    m.onFinished = resolve;
    m.play(z);
  });
}

btn.onclick = playAll;
<script src="https://fkurz.net/ham/jscwlib/src/jscwlib.js"></script>
<button id="btn">play all</button>