zerowords
zerowords

Reputation: 3113

Safari: Promise "syntaxError: Unexpected keyword 'function'. Expected ')' "

This code works in Chrome, but fails with Subject's syntax error in Safari in line 2. Also, in iOS the Safari user is asked for permission to use their microphone but recording fails. All is well with Android Chrome.

Fiddle shows more

Code is based on

index.js:

var recordAudio = function recordAudio() {
  return new Promise(async function(resolve) {
    var stream = await navigator.mediaDevices.getUserMedia({
      audio: true
    });
    var mediaRecorder = new MediaRecorder(stream);
    var audioChunks = [];
    mediaRecorder.addEventListener("dataavailable", function(event) {
      audioChunks.push(event.data);
    });

    var start = function start() {
      audioChunks = [];
      mediaRecorder.start();
    };

    var stop = function stop() {
      return new Promise(function(resolve) {
        mediaRecorder.addEventListener("stop", function() {
          var audioBlob = new Blob(audioChunks);
          var audioUrl = URL.createObjectURL(audioBlob);
          var audio = new Audio(audioUrl);

          var play = function play() {
            return audio.play();
          };

          resolve({
            audioChunks: audioChunks,
            audioBlob: audioBlob,
            audioUrl: audioUrl,
            play: play
          });
        });
        mediaRecorder.stop();
      });
    };

    resolve({
      start: start,
      stop: stop
    });
  });
};

Upvotes: 0

Views: 1274

Answers (2)

Barmar
Barmar

Reputation: 780919

Support for async functions was added in Safari 10.1. You're doing your testing in 9.1, which is too old.

If you need your application to be compatible with such an old Safari version (it's from 2016) you'll have to use explicit Promise code rather than async and await.

Upvotes: 1

Keith
Keith

Reputation: 155662

You're mixing Promise and async syntax, the error from Safari is telling you that it doesn't expect an async function, which makes sense as you're resolving a promise with another promise.

Change function recordAudio to async function recordAudio and remove the new Promise entirely and just use await instead.

Any function that uses await will return a Promise anyway.

async function recordAudio() {
    var stream = await navigator.mediaDevices.getUserMedia({
      audio: true
    });
    var mediaRecorder = new MediaRecorder(stream);
    var audioChunks = [];
    mediaRecorder.addEventListener("dataavailable", function(event) {
      audioChunks.push(event.data);
    });

    var start = function start() {
      audioChunks = [];
      mediaRecorder.start();
    };

    var stop = function stop() {
      return new Promise(function(resolve) {
        mediaRecorder.addEventListener("stop", function() {
          var audioBlob = new Blob(audioChunks);
          var audioUrl = URL.createObjectURL(audioBlob);
          var audio = new Audio(audioUrl);

          var play = function play() {
            return audio.play();
          };

          resolve({
            audioChunks: audioChunks,
            audioBlob: audioBlob,
            audioUrl: audioUrl,
            play: play
          });
        });
        mediaRecorder.stop();
      });
    };

    return {
      start: start,
      stop: stop
    };
};

Upvotes: 0

Related Questions