0

I am making voice recorder and i am working this with promise async to learn async .

This is my code and works fine for one time call but once i call function recursively at end of the function handleAction it starts to act weird .

I dont know why but code isnot working on Snippet.

It works fine if i don't call handleAction() function at the end of handlefunction function

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>
Pravin Poudel
  • 1,433
  • 3
  • 16
  • 38
  • [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! – Bergi Aug 07 '19 at 21:31

1 Answers1

0

It is because, your handleAction() function is an asynchronous function. in the end, Try calling it like:

return await handleAction();

Hope this helps :)

Mohammed Amir Ansari
  • 2,311
  • 2
  • 12
  • 26