Currently, I am developing an application that requires recording audio using a microphone and transmitting it to a backend server (tomcat). However, I have encountered an issue where sending large streams causes Angular to become unresponsive and freezes the browser.
To capture the audio file, I utilize the native function RecorderWorkerFactory.getUserMedia() to obtain a RecordBlob object in Angular. Subsequently, I extract the audio data into base64 encoding and send it to the backend server using $resource. The backend successfully receives and processes the data, but Firefox detects an infinite loop during the callback execution, resulting in a freeze.
Despite this issue, if the program continues to run, the page refresh eventually proceeds after a long delay.
The following code snippet demonstrates how I extract and send the audio content in base64 format:
var blob = $scope.audio.recordBlob;
if (blob) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
$scope.audioContent = reader.result;
$scope.sendMessage();
}
}
$scope.sendMessage = function(){
var outputStream = {
"audio": $scope.audioContent
};
$scope.sendIM(outputStream);
}
I send the outputStream via POST request to the backend and trigger the loadData() function in the callback to reload the view.
services.FileCreation= $resource(URI_SERVICE_CREATION, {}, {
'post' : urlEncodedFormPost
});
$scope.sendIM = function(fluxSortie) {
$services.FileCreation.post(angular.toJson(outputStream)).$promise.then(function(result){
$scope.loadData();
});
}
Additionally, here is the Java code for creating the audio file:
private void createAudioFile(File file, byte[] content) throws IOException {
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file.getPath());
IOUtils.write(content, stream);
} catch (IOException e) {
LOGGER.debug("creation failed");
} finally {
if (stream != null) {
stream.flush();
stream.close();
}
}
}
The content variable contains the conversion of the sent base64 string.
After investigating, I discovered that the infinite loop occurs in a native Angular function called shallowClearAndCopy(), which triggers after the Java execution but before the callback. This function seemingly converts each character of the base64-encoded audio string into an object property and loops through them for deletion. Consequently, Firefox interprets this as an infinite loop.
function shallowClearAndCopy(src, dst) {
dst = dst || {};
angular.forEach(dst, function(value, key) { // The freezing point, iterating over all characters of the base64 encoded data
delete dst[key];
});
for (var key in src) {
if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
dst[key] = src[key];
}
}
return dst;
}
Is this performance issue related to AngularJS, or is there a solution I might be overlooking? Could there be an error in my callback setup?
Thanks for any insights!