如何在第一次播放声音后才真假值

时间:2018-04-12 13:07:14

标签: javascript reactjs html5-audio

我的人数据包含动态布尔值。该值自动生成,每次都可以为true或false。

网页每5秒获取一次数据并进行渲染。如果每个人的值都是假,则播放声音。

这是代码:

import React, { Component } from 'react';
import { render } from 'react-dom';
import Sound from './Mp3';

const data = [
  {
    id: '1',
    name: 'Peter',
    value: true
  },
  {
    id: '2',
    name: 'John',
    value: false
  }
];

class App extends Component {
  state = {
    results: [],
  }

  componentDidMount() {
    this.getData()
    // get data every 5 sec
    setInterval(this.getData, 5000);
  }

  getData = () => {
    // generate random value
    data[0].value = Math.random() >= 0.5;
    data[1].value = Math.random() >= 0.5;

    // set results state to data
    this.setState({ results: data });

    // condition if John or Peter value is false
    if (data.some(d => d.value === false)) {
      var audio = new Audio(Sound);
      // play a sound
      audio.play();
    }
  }

  render() {
    const { results } = this.state;
    return (
      <div>
        {results.map(item => {
          return (
            <div key={item.id}>
              <div>
                Name: {item.name}
              </div>
              <div>
                Value: {item.value.toString()}
              </div>
              <br />
            </div>
          )
        })}
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

这是demo

使用上面的代码,如果每个人的值都为假,则每次都会播放声音。

如何在第一次播放声音后才会出现真值?

我的意思是,如果第一个渲染的John值为false,则播放声音,如果5秒后John值仍为false,则在值返回true后再播放声音并再次更改为false。

结果我期待:

// first rendered
Name: Peter
Value: true  

Name: John
Value: false  // play a sound

// second (5 seconds later)
Name: Peter
Value: true  

Name: John
Value: false  // don't play a sound

// third (10 seconds later)
Name: Peter
Value: true  

Name: John
Value: true  // don't play a sound

// fourth (15 seconds later)
Name: Peter
Value: true  

Name: John
Value: false  // play a sound

...

2 个答案:

答案 0 :(得分:1)

您需要跟踪每个用户在另一个对象内部的getData函数之外的先前值,然后将之前的值与其他对象中的新值进行比较。

  state = {
    results: []
  }

  const previousResults = {};

  componentDidMount() {
    this.getData()
    // get data every 5 sec
    setInterval(this.getData, 5000);
  }

  getData = () => {
    // generate random value
    data[0].value = Math.random() >= 0.5;
    data[1].value = Math.random() >= 0.5;

    // set results state to data
    this.setState({ results: data });

    // condition if user value is false & previous result for user was not false
    if (data.some(d => (d.value === false) && (this.previousResults[d.id] !== false))) {
      var audio = new Audio(Sound);
      // play a sound
      audio.play();
    }

    data.forEach((item) => {
      this.previousResults[item.id] = item.value;
    });
  }

答案 1 :(得分:0)

您可以使用一种“断路器”来跟踪其状态,以及是否已启用。在绊倒之后,它会在重新启用之前等待一段时间。

以下代码演示了以下内容

  • true切换到false执行action回调
  • 继续脉冲false不会重复此操作
  • 切换到true,然后等待timeout之前的时间更长,然后再次发出新的false执行action回调。

function TFCircuitBreaker(timeout, action){
    this.state = null;
    this.enabled = true;
    
    this.valueChange = function(newValue){
        if(this.enabled){         
          if(this.state && !newValue){
              action();
              this.enabled = false;
              setTimeout( () => this.enabled = true,timeout);
          }
        }
        this.state = newValue;
    }
}

var cb = new TFCircuitBreaker(5000, () => console.log("Play sound"));
cb.valueChange(true);
cb.valueChange(false);
cb.valueChange(true);
cb.valueChange(false);

cb.valueChange(true);
setTimeout( () => cb.valueChange(false), 6000);

我也用类似的代码更新了你的演示,我认为你做了你想要的:https://stackblitz.com/edit/react-kmfiij?embed=1&file=index.js