我正在制作录音机,我正在使用 promise async 来学习 async 。
这是我的代码,一次调用可以正常工作,但是一旦我在函数handleAction结束时递归调用函数,它就会开始表现得很奇怪。
我不知道为什么,但代码在 Snippet 上不起作用。
如果我不在handlefunction函数的末尾调用handleAction()函数,它工作正常
const recordAudio = () =>
new Promise(async resolve => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); //it return a promise that resolves to a mediastream object.
const mediaRecorder = new MediaRecorder(stream); // provide functionality to easily record media
//mediastream interface represent a stream of media content . A stream consists of several tracks such as videa nad audio
const audioChunks = [];
mediaRecorder.addEventListener('dataavailable', event => {
audioChunks.push(event.data);
});
const start = () => mediaRecorder.start();
const stop = () =>
new Promise(async resolve => {
mediaRecorder.addEventListener('stop', () => {
const audioblob = new Blob(audioChunks);
// const audioChunks = [];
const audioURL = URL.createObjectURL(audioblob);
const audio = new Audio(audioURL);
const play = () => audio.play();
resolve({ audioblob, audioURL, play });
});
mediaRecorder.stop();
// set the mediarecorder.state to "inactive" and stop capturing media raise a dataavailable evenet containing the bolb of data that has been gathered
});
resolve({ start, stop });
});
const later = (delay, value) => {
let timer = 0;
let reject = null;
const promise = new Promise((resolve, _reject) => {
reject = _reject;
timer = setTimeout(resolve, delay, value);
});
return {
get promise() {
return promise;
},
cancel() {
if (timer) {
clearTimeout(timer);
timer = 0;
reject();
reject = null;
}
}
};
};
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
var audio = "";
var recorder = "";
const handleAction = async () => {
const data_rep = document.getElementById('loop-number-input').value * 1000;
const actionButton = document.getElementsByClassName('record_button_inside');
const color_change = document.getElementsByClassName('record_button_inside')[0];
const actionButton_p = document.getElementsByClassName('state_info')[0];
actionButton.disabled = true;
color_change.style.background = 'red';
actionButton_p.innerText = "RECORDING";
var element = document.getElementById('myBar');
var width = 1;
recorder = await recordAudio();
recorder.start();
var id = setInterval(frame, document.getElementById('loop-number-input').value * 10);
await sleep(data_rep);
// this is display bar to show how much time left for recording
function frame() {
if (width >= 100) {
console.log("entered");
clearInterval(id);
width = 1;
} else {
width++;
element.style.width = width + '%';
}
}
audio = await recorder.stop();
audio.play();
var id2 = setInterval(frame_after, document.getElementById('loop-number-input').value * 9.5);
// this is bar to display the percentage of sound played
function frame_after() {
var element = document.getElementById('myBar');
element.style.background = 'red';
if (width >= 100) {
console.log("entered");
clearInterval(id2);
element.style.width = 1;
} else {
width++;
element.style.width = width + '%';
}
}
actionButton_p.innerText = "playing !!!!";
color_change.style.background = 'inherit';
actionButton.disabled = false;
// if(document.getElementById('loopcheck').checked){
handleAction();
// }
}
body{
background: #e4b60c !important;
height: 100vh;
}
h1.title{
font-family: 'Roboto', sans-serif !important;
padding-bottom: 12px ;
border-bottom: 1px solid #5a5a5a40;
}
#loop-number-input{
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16), 0 2px 10px 0 rgba(0,0,0,0.12);
}
.record_button_inside {
background-color: #673AB7;
padding: 10px;
border-radius: 50%;
width: 60px;
height: 60px;
border-color: transparent;
color: white;
font-size: 26px;
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16), 0 2px 10px 0 rgba(0,0,0,0.12);
}
.replay_button{
float: right;
width: 40px;
height: 40px;
font-size: 20px;
padding: inherit;
}
.record_button_inside:focus {
/*background-color: transparent;*/
border: none;
}
.padd {
margin: 30px 0px;
}
.recorder_div{
position: relative;
top: 25%;
/*height: 100vh;*/
}
.recorder_div div ,h1 , p {
position: relative;
top: 25%;
}
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background-color: #4CAF50;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="recorder_div">
<h1 class="title">Audio Recording Test</h1>
<div class="form-group row padd ">
<label for="example-number-input" class="col-3 col-form-label">Enter the time for the loop (default is 5 seconds)</label>
<div class="col-6">
<input class="form-control" type="number" value="5" id="loop-number-input" style="max-width: 250px;margin-bottom: 30px;">
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="loopcheck" value="option1">
<label class="form-check-label" for="inlineCheckbox1">Check for auto play and record continously </label>
</div>
<p>sing for input loop seconds, then you will hear your recording played back</p>
<div>
<button class="record_button_inside" id="action" onclick="handleAction()">
<i class="fas fa-microphone-alt"></i>
</button>
<!-- <button class="record_button_inside replay_button" id="action" onclick="handleAction('False')">
<i class="fas fa-redo-alt"></i>
</button> -->
<hr />
<div id="myProgress">
<div id="myBar"></div>
</div>
<p class="state_info">Start recording...</p>
</div>
</div>
</div>
</div>
</div>