【问题标题】:convert const async function into React将 const 异步函数转换为 React
【发布时间】:2020-05-26 15:01:30
【问题描述】:

我有一个 React 类,我在其中使用一个 vanilla js 程序,并尝试将它实现为一个 React 类。最终状态应该是一个音乐发生器。

现在,我得到了很棒的音频,但这只是一个静态序列。最酷的部分在 const async 函数中。一般来说,作为前端新手,我不确定如何将 const async 函数转换为 react 组件的可用部分,以便它不只是播放音符序列,而是实际运行 rnn。

这是课程:

class Beat3 extends React.Component {
  constructor(props) {
    super(props);
    this.improvCheckpoint = 'https://storage.googleapis.com/magentadata/js/checkpoints/music_rnn/chord_pitches_improv'
    this.improvRNN = new mm.MusicRNN(this.improvCheckpoint)
    this.synth = new Tone.Synth().toMaster()
    const { midi, Note } = Tonal
    this.player = new mm.Player();

    this.sequence = {
      BEATB: {
      ticksPerQuarter: 360,
      totalTime: 2,
      timeSignatures: [{ time: 0, numerator: 4, denominator: 4 }],
      tempos: [{ time: 0, qpm: 300 }],
      notes: [
        { pitch: 60.3, startTime: 0, endTime: 0.9 },
        { pitch: 65.4, startTime: 0.9, endTime: 1.9 },
        { pitch: 67.2, startTime: 1.9, endTime: 2.7 },
      ]
    }
  }

    this.quantizedSequence = mm.sequences.quantizeNoteSequence(this.sequence, 1)

    /*This is what Im trying to have run in the react class*/

    const startProgram = async () => {
    try {
    await this.improvRNN.initialize()
    let improvisedMelody = await this.improvRNN.continueSequence(
      this.quantizedSequence, 60, 1.1, [60, 75,67,69])

    const playOriginalMelody = () => {
      this.sequence.notes.forEach(note => {
        this.synth.triggerAttackRelease(Note.fromMidi(note.pitch),
        note.endTime - note.startTime, note.startTime)
      })
    }

    const playGeneratedMelody = () => {
      improvisedMelody.notes.forEach(note => {
        this.synth.triggerAttackRelease(Note.fromMidi(note.pitch),
        note.quantizedEndStep - note.quantizedStartStep, note.quantizedStartStep)
      })
    }

    const originalMelodyButton = document.getElementById('b1a')
    const generatedMelodyButton = document.getElementById('b1b')
    originalMelodyButton.onclick = () => {
      playOriginalMelody()
    }
    generatedMelodyButton.onclick = () => {
      playGeneratedMelody()
    }

  } catch (error) {
    console.error(error)
  }
 }
}

  componentDidMount() {
    this.player.start(this.sequence.BEATB);
  }

  componentWillUnmount() {
    this.player.stop();
  }

  render()
  {
    return (
      <div class="b1a">
      </div>
    );
  }
}

export default Beat3

当我将异步添加到 componentDidMount 时,声音仍然出现,但里面的 const 按钮不显示。我相信这是一个简单的解决方法,并且解释如何在此处执行将非常有帮助。

componentDidMount 与异步:

componentDidMount() {
    this.player.start(this.sequence.BEATB);
    const startProgram = async () => {
    try {
    await this.improvRNN.initialize()
    let improvisedMelody = await this.improvRNN.continueSequence(
      this.quantizedSequence, 60, 1.1, [60, 75,67,69])
    const playOriginalMelody = () => {
      this.sequence.notes.forEach(note => {
        this.synth.triggerAttackRelease(Note.fromMidi(note.pitch),
        note.endTime - note.startTime, note.startTime)
      })
    }
    const playGeneratedMelody = () => {
      improvisedMelody.notes.forEach(note => {
        this.synth.triggerAttackRelease(Note.fromMidi(note.pitch),
        note.quantizedEndStep - note.quantizedStartStep, note.quantizedStartStep)
      })
    }
    const originalMelodyButton = document.getElementById('b1a')
    const generatedMelodyButton = document.getElementById('b1b')
    originalMelodyButton.onclick = () => {
      playOriginalMelody()
    }
    generatedMelodyButton.onclick = () => {
      playGeneratedMelody()
    }
  } catch (error) {
    console.error(error)
  }
}
}

一如既往,感谢您的帮助。

【问题讨论】:

  • 为什么不能在componentDidMount() 中调用它?在这种情况下,您应该添加async
  • 添加了它,并更新了问题。按钮仍然没有显示,所以我无法测试它。
  • 你不是在调用它,你只是在里面定义函数。我会在答案中告诉你。
  • 非常感谢巴勃罗

标签: javascript reactjs magenta


【解决方案1】:

如果你想从 ComponentDidMount 调用startProgram 函数(当组件被加载到应用程序中时):

async componentDidMount() {
    this.player.start(this.sequence.BEATB);

    await startProgram();
}

但是,考虑到在 React 中为按钮分配行为的理想通常是通过在 JSX 中的 render() 函数中声明它们并使用 onClick 属性分配行为。

例如,第一个按钮(实际上是div)可以像这样添加其行为(您需要在类级别或render() 内声明playOriginalMelody):

render()
{
  return (
    <div class="b1a" onClick={playOriginalMelody}>
    </div>
  );
}

【讨论】:

  • @VP9 在这里查看:codeshare.io/2KExlz(我无法编辑你的)。不过,您需要对其进行测试。但想法是直接在 div 中分配行为。对于第二个更复杂的 div 重构(我没有在那里做),因为你依赖于improvisedMelody。这应该是组件状态的一部分,以便您能够在以下操作中使用它。
  • 现在代码的问题在于,您甚至可以在startProgram 完成运行之前单击按钮。理想情况下,应该根据组件状态阻止按钮,直到异步操作完成。
猜你喜欢
  • 1970-01-01
  • 2015-06-25
  • 2012-07-25
  • 1970-01-01
  • 2014-03-29
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多