javascript - 从复杂函数返回字符串

标签 javascript audio return blob

Javascript 问题:如何从此处显示的函数返回所需的 url:

function getAudioBlob() {
 return recorder && recorder.exportWAV(function (blob) {
   var url = URL.createObjectURL(blob);
   console.log(url) // works great!
   return url;
 }, ("audio/mp3"));
}

console.log(getAudioBlob()); // the log reads 'undefined'

我在获取从此函数返回的 URL 字符串(用于音频 blob)时遇到问题。我的目标是能够使用 Blob Url 将录音上传到服务器。

我的问题源于我不知道如何从这种尴尬的安排中获取返回的值:

recorder && recorder.exportWAV(function (blob) {...

我在它前面放了一个“return”,但这显然不起作用。我该如何重写它呢?谢谢!

最佳答案

exportWAV 是异步的,因此它会在您的函数执行后完成。您可以在准备就绪时使用回调或 Promise 运行一些代码。 .例如:

function getAudioBlob(recorder) {
  return new Promise((resolve) => {
    recorder.exportWAV((blob) => {
      const url = URL.createObjectURL(blob);
      resolve(url);
    }, 'audio/mp3');
  });
}

// Use the function..
if (recorder) {
  getAudioBlob(recorder).then(url => console.log('blob url:', url));
}

完成 url 后,您应该调用 URL.revokeObjectURL(url) 来释放内存。

我很关心您所说的“我的目标是能够使用 Blob Url 将录音上传到服务器”的意思。您创建的 URL 仅适用于该客户,并且仅在该选项卡打开时存在。

下面是针对您的整个问题的一些 PoC 代码:

// This is a shorthand for writing a function that returns something.
const getAudioBlob = recorder =>
  new Promise(resolve => recorder.exportWAV(resolve, 'audio/mp3'));

function uploadBlobToServer(blob) {
  const fd = new FormData();
  fd.append('recording', blob, 'recording.mp3');
  return fetch('/api/recording/upload', { method: 'POST', body: fd });
}

function stopRecording() {
  if (!recorder) {
    console.error('No recorder found');
    return;
  }

  recorder.stop();
  getAudioBlob(recorder).then((blob) => {
    // Not sure what this is but guessing it needs to be called
    // AFTER exportWAV has finished?
    recorder.clear();

    // When we return a Promise inside another, the subsequent .then()/.catch()
    // Will have the result of this promise (in this case the result of the upload).
    return uploadBlobToServer(blob);
  })
    .then((res) => {
      if (res.status > 400) {
        throw new Error(res.statusText);
      }
    })
    .then((res) => {
      console.log('Recording uploaded to server successfully.', res.status, res.statusText);
    })
    .catch((error) => {
      console.error('Failed to upload recording to server.', error);
    });
}

// Or this is how you could write that function using asyc/await which is a bit cleaner
// than using the Promises directly, but it's only supported by new browser versions.
async function stopRecording() {
  if (!recorder) {
    console.error('No recorder found');
    return;
  }

  recorder.stop();

  try {
    const blob = await getAudioBlob(recorder);
    const res = await uploadBlobToServer(blob);

    // The HTTP Status code from the server was an error.
    if (res.status > 400) {
      throw new Error(res.statusText);
    }

    console.log('Recording uploaded to server successfully.', res.status, res.statusText);

    recorder.clear();
  } catch (error) {
    console.error('Failed to create and upload your recording:', error);
  }
}

关于javascript - 从复杂函数返回字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49560619/

相关文章:

javascript - 从显示的 Ajax 请求获取数据

actionscript-3 - 在不更改音调的情况下动态更改as3中声音的播放速度

c# - 在 C# 中查看返回值

javascript - 从 Meteor 的数据库中填充 HTML Select 下拉列表

javascript - 如何从vba中查找和调​​用javascript方法

javascript - 如何使用 JavaScript 打印对象数组

javascript - 在 HTML 中更新屏幕上的区间变量

python - 语音识别无法正常工作(未检测到麦克风)

.net - 是否有用于通用音频文件解码的 .NET 库?

arrays - 逐行解析数组并将其分解为更多数组