代码之家  ›  专栏  ›  技术社区  ›  Ras

如何仅在第一次播放声音为true后为false值

  •  1
  • Ras  · 技术社区  · 6 年前

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

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

    代码如下:

    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

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

    如何在第一时间播放一个声音,假值为真后才播放?

    我的意思是,如果第一个渲染的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 回复  |  直到 6 年前
        1
  •  1
  •   jdgower    6 年前

    您需要在另一个对象的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;
        });
      }
    
        2
  •  0
  •   Jamiec    6 年前

    您可以使用一种“断路器”,它可以跟踪其状态以及是否启用。跳闸后,它会等待一段时间,然后重新启用自身。

    下面的代码演示了以下内容

    • 从切换 true false 执行 action 回调函数
    • 继续脉冲 错误的 不重复此操作
    • 切换到 符合事实的 然后等待的时间比 timeout 在启动新的 错误的 再次执行 行动 回调。

    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