【问题标题】:How to play a sound only at the first time false value after true真后如何只在第一次假值时播放声音
【发布时间】:2018-04-13 03:59:25
【问题描述】:

我有包含动态布尔值的人员数据。该值是自动生成的,每次都可以为真或假。

网页每 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

...

【问题讨论】:

  • 第一种情况 - John 有一个真正的价值,但你的要求是 With the code above, the sound is played every time if the value on each person is false. 你能解释一下吗?
  • 先生。 Asiniy,是的,Peter 有一个 true 值,John 有一个 false 值,它会每 5 秒自动生成随机的 true 或 false。所以对于第一次渲染,声音只播放 John false 值。
  • 对不起 Asiniy 先生,我的代码数据和我期望的结果数据看起来不同。我已经更新了我的问题。

标签: javascript reactjs html5-audio


【解决方案1】:

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

  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;
    });
  }

【讨论】:

  • 非常感谢您的回答,您能告诉我如何使用我的代码做到这一点吗?
  • 非常感谢Jdgower先生,我试过了,效果很好。
【解决方案2】:

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

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

  • 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

【讨论】:

  • 非常感谢您的回答,但我不知道如何将您上面的代码与演示代码结合起来。
  • @Ras 你看到我回答的最后一行了吗?
  • @Jamec 最后一行我没有注意到你,对此我很抱歉。我尝试在上面查看您的链接,但似乎有所不同,如果值为 false,我想播放声音,并且在您的链接上听起来以真实值播放。当我看时,如果 peter 值从 true 变为 false 并且 john 从 false 变为 true,它似乎不会播放声音。我的意思是,我想播放一个声音,每个人的数据都从真变为假。
  • @Ras 如果你不能否定一个布尔值,你就没有机会编写这段代码!
  • @Jamec 很抱歉让您生气了。通过上面的链接,我看不到您更新的代码。能否请出示一下代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多