如何仅在第一次播放声音 false value after true
How to play a sound only at the first time false value after true
我有包含动态布尔值的人员数据。该值是自动生成的,每次可以为真或假。
网页每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
使用上面的代码,如果每个人的值都是假的,每次都会播放声音。
如何在true后第一次只播放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
...
您可以使用一种 "Circuit Breaker" 来跟踪其状态以及是否已启用。跳闸后,它会等待一段时间再重新启用。
下面的代码演示了以下内容
- 从
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
您需要在另一个对象内的 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;
});
}
我有包含动态布尔值的人员数据。该值是自动生成的,每次可以为真或假。
网页每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
使用上面的代码,如果每个人的值都是假的,每次都会播放声音。
如何在true后第一次只播放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
...
您可以使用一种 "Circuit Breaker" 来跟踪其状态以及是否已启用。跳闸后,它会等待一段时间再重新启用。
下面的代码演示了以下内容
- 从
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
您需要在另一个对象内的 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;
});
}