Javascript问题:如何从此处显示的功能返回我想要的网址:
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) {...
我放了一个'返回'在它面前,但显然不起作用。我该如何重写它呢?谢谢!
答案 0 :(得分:4)
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.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);
}
}